diff options
Diffstat (limited to 'drivers')
51 files changed, 1243 insertions, 6381 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index cf5d8b86da8f..62b2acf2a764 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -98,7 +98,6 @@ obj-$(CONFIG_DIO) += dio/ obj-$(CONFIG_SBUS) += sbus/ obj-$(CONFIG_ZORRO) += zorro/ obj-$(CONFIG_ATA_OVER_ETH) += block/aoe/ -obj-$(CONFIG_PARIDE) += block/paride/ obj-$(CONFIG_TC) += tc/ obj-$(CONFIG_USB_PHY) += usb/ obj-$(CONFIG_USB) += usb/ diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 0b6358a5b315..b56fba76b43f 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -1144,6 +1144,20 @@ config PATA_WINBOND_VLB Support for the Winbond W83759A controller on Vesa Local Bus systems. +config PATA_PARPORT + tristate "Parallel port IDE device support" + depends on PARPORT_PC + help + There are many external CD-ROM and disk devices that connect through + your computer's parallel port. Most of them are actually IDE devices + using a parallel port IDE adapter. This option enables the + PATA_PARPORT subsystem which contains drivers for many of these + external drives. + Read <file:Documentation/admin-guide/blockdev/paride.rst> for more + information. + +source "drivers/ata/pata_parport/Kconfig" + comment "Generic fallback / legacy drivers" config PATA_ACPI diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 4ee5c0761d90..20e6645ab737 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -112,6 +112,8 @@ obj-$(CONFIG_PATA_RZ1000) += pata_rz1000.o obj-$(CONFIG_PATA_PXA) += pata_pxa.o +obj-$(CONFIG_PATA_PARPORT) += pata_parport/ + # Should be last but two libata driver obj-$(CONFIG_PATA_ACPI) += pata_acpi.o # Should be last but one libata driver diff --git a/drivers/ata/acard-ahci.c b/drivers/ata/acard-ahci.c index 7654a40c12b4..993eadd173da 100644 --- a/drivers/ata/acard-ahci.c +++ b/drivers/ata/acard-ahci.c @@ -57,7 +57,7 @@ struct acard_sg { }; static enum ata_completion_errors acard_ahci_qc_prep(struct ata_queued_cmd *qc); -static bool acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc); +static void acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc); static int acard_ahci_port_start(struct ata_port *ap); static int acard_ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -248,7 +248,7 @@ static enum ata_completion_errors acard_ahci_qc_prep(struct ata_queued_cmd *qc) return AC_ERR_OK; } -static bool acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc) +static void acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc) { struct ahci_port_priv *pp = qc->ap->private_data; u8 *rx_fis = pp->rx_fis; @@ -263,13 +263,11 @@ static bool acard_ahci_qc_fill_rtf(struct ata_queued_cmd *qc) * Setup FIS. */ if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE && - !(qc->flags & ATA_QCFLAG_FAILED)) { + !(qc->flags & ATA_QCFLAG_EH)) { ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf); qc->result_tf.status = (rx_fis + RX_FIS_PIO_SETUP)[15]; } else ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf); - - return true; } static int acard_ahci_port_start(struct ata_port *ap) diff --git a/drivers/ata/ahci_octeon.c b/drivers/ata/ahci_octeon.c index b9460b91288f..5021ab3ede49 100644 --- a/drivers/ata/ahci_octeon.c +++ b/drivers/ata/ahci_octeon.c @@ -73,11 +73,6 @@ static int ahci_octeon_probe(struct platform_device *pdev) return 0; } -static int ahci_octeon_remove(struct platform_device *pdev) -{ - return 0; -} - static const struct of_device_id octeon_ahci_match[] = { { .compatible = "cavium,octeon-7130-sata-uctl", }, { /* sentinel */ } @@ -86,7 +81,6 @@ MODULE_DEVICE_TABLE(of, octeon_ahci_match); static struct platform_driver ahci_octeon_driver = { .probe = ahci_octeon_probe, - .remove = ahci_octeon_remove, .driver = { .name = "octeon-ahci", .of_match_table = octeon_ahci_match, diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 29acc35bf4a6..8f216de76648 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -55,7 +55,8 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); static int ahci_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); -static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc); +static void ahci_qc_fill_rtf(struct ata_queued_cmd *qc); +static void ahci_qc_ncq_fill_rtf(struct ata_port *ap, u64 done_mask); static int ahci_port_start(struct ata_port *ap); static void ahci_port_stop(struct ata_port *ap); static enum ata_completion_errors ahci_qc_prep(struct ata_queued_cmd *qc); @@ -157,6 +158,7 @@ struct ata_port_operations ahci_ops = { .qc_prep = ahci_qc_prep, .qc_issue = ahci_qc_issue, .qc_fill_rtf = ahci_qc_fill_rtf, + .qc_ncq_fill_rtf = ahci_qc_ncq_fill_rtf, .freeze = ahci_freeze, .thaw = ahci_thaw, @@ -1847,18 +1849,47 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) ata_port_abort(ap); } -static void ahci_handle_port_interrupt(struct ata_port *ap, - void __iomem *port_mmio, u32 status) +static void ahci_qc_complete(struct ata_port *ap, void __iomem *port_mmio) { struct ata_eh_info *ehi = &ap->link.eh_info; struct ahci_port_priv *pp = ap->private_data; - struct ahci_host_priv *hpriv = ap->host->private_data; - int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING); u32 qc_active = 0; int rc; + /* + * pp->active_link is not reliable once FBS is enabled, both + * PORT_SCR_ACT and PORT_CMD_ISSUE should be checked because + * NCQ and non-NCQ commands may be in flight at the same time. + */ + if (pp->fbs_enabled) { + if (ap->qc_active) { + qc_active = readl(port_mmio + PORT_SCR_ACT); + qc_active |= readl(port_mmio + PORT_CMD_ISSUE); + } + } else { + /* pp->active_link is valid iff any command is in flight */ + if (ap->qc_active && pp->active_link->sactive) + qc_active = readl(port_mmio + PORT_SCR_ACT); + else + qc_active = readl(port_mmio + PORT_CMD_ISSUE); + } + + rc = ata_qc_complete_multiple(ap, qc_active); + if (unlikely(rc < 0 && !(ap->pflags & ATA_PFLAG_RESETTING))) { + ehi->err_mask |= AC_ERR_HSM; + ehi->action |= ATA_EH_RESET; + ata_port_freeze(ap); + } +} + +static void ahci_handle_port_interrupt(struct ata_port *ap, + void __iomem *port_mmio, u32 status) +{ + struct ahci_port_priv *pp = ap->private_data; + struct ahci_host_priv *hpriv = ap->host->private_data; + /* ignore BAD_PMP while resetting */ - if (unlikely(resetting)) + if (unlikely(ap->pflags & ATA_PFLAG_RESETTING)) status &= ~PORT_IRQ_BAD_PMP; if (sata_lpm_ignore_phy_events(&ap->link)) { @@ -1867,6 +1898,12 @@ static void ahci_handle_port_interrupt(struct ata_port *ap, } if (unlikely(status & PORT_IRQ_ERROR)) { + /* + * Before getting the error notification, we may have + * received SDB FISes notifying successful completions. + * Handle these first and then handle the error. + */ + ahci_qc_complete(ap, port_mmio); ahci_error_intr(ap, status); return; } @@ -1903,32 +1940,8 @@ static void ahci_handle_port_interrupt(struct ata_port *ap, } } - /* pp->active_link is not reliable once FBS is enabled, both - * PORT_SCR_ACT and PORT_CMD_ISSUE should be checked because - * NCQ and non-NCQ commands may be in flight at the same time. - */ - if (pp->fbs_enabled) { - if (ap->qc_active) { - qc_active = readl(port_mmio + PORT_SCR_ACT); - qc_active |= readl(port_mmio + PORT_CMD_ISSUE); - } - } else { - /* pp->active_link is valid iff any command is in flight */ - if (ap->qc_active && pp->active_link->sactive) - qc_active = readl(port_mmio + PORT_SCR_ACT); - else - qc_active = readl(port_mmio + PORT_CMD_ISSUE); - } - - - rc = ata_qc_complete_multiple(ap, qc_active); - - /* while resetting, invalid completions are expected */ - if (unlikely(rc < 0 && !resetting)) { - ehi->err_mask |= AC_ERR_HSM; - ehi->action |= ATA_EH_RESET; - ata_port_freeze(ap); - } + /* Handle completed commands */ + ahci_qc_complete(ap, port_mmio); } static void ahci_port_intr(struct ata_port *ap) @@ -2053,11 +2066,18 @@ unsigned int ahci_qc_issue(struct ata_queued_cmd *qc) } EXPORT_SYMBOL_GPL(ahci_qc_issue); -static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc) +static void ahci_qc_fill_rtf(struct ata_queued_cmd *qc) { struct ahci_port_priv *pp = qc->ap->private_data; u8 *rx_fis = pp->rx_fis; + /* + * rtf may already be filled (e.g. for successful NCQ commands). + * If that is the case, we have nothing to do. + */ + if (qc->flags & ATA_QCFLAG_RTF_FILLED) + return; + if (pp->fbs_enabled) rx_fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ; @@ -2068,9 +2088,12 @@ static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc) * Setup FIS. */ if (qc->tf.protocol == ATA_PROT_PIO && qc->dma_dir == DMA_FROM_DEVICE && - !(qc->flags & ATA_QCFLAG_FAILED)) { + !(qc->flags & ATA_QCFLAG_EH)) { ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf); qc->result_tf.status = (rx_fis + RX_FIS_PIO_SETUP)[15]; + qc->flags |= ATA_QCFLAG_RTF_FILLED; + return; + } /* * For NCQ commands, we never get a D2H FIS, so reading the D2H Register @@ -2080,15 +2103,85 @@ static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc) * instead. However, the SDB FIS does not contain the LBA, so we can't * use the ata_tf_from_fis() helper. */ - } else if (ata_is_ncq(qc->tf.protocol)) { + if (ata_is_ncq(qc->tf.protocol)) { const u8 *fis = rx_fis + RX_FIS_SDB; + /* + * Successful NCQ commands have been filled already. + * A failed NCQ command will read the status here. + * (Note that a failed NCQ command will get a more specific + * error when reading the NCQ Command Error log.) + */ qc->result_tf.status = fis[2]; qc->result_tf.error = fis[3]; - } else - ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf); + qc->flags |= ATA_QCFLAG_RTF_FILLED; + return; + } + + ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf); + qc->flags |= ATA_QCFLAG_RTF_FILLED; +} + +static void ahci_qc_ncq_fill_rtf(struct ata_port *ap, u64 done_mask) +{ + struct ahci_port_priv *pp = ap->private_data; + const u8 *fis; + + /* No outstanding commands. */ + if (!ap->qc_active) + return; + + /* + * FBS not enabled, so read status and error once, since they are shared + * for all QCs. + */ + if (!pp->fbs_enabled) { + u8 status, error; + + /* No outstanding NCQ commands. */ + if (!pp->active_link->sactive) + return; + + fis = pp->rx_fis + RX_FIS_SDB; + status = fis[2]; + error = fis[3]; - return true; + while (done_mask) { + struct ata_queued_cmd *qc; + unsigned int tag = __ffs64(done_mask); + + qc = ata_qc_from_tag(ap, tag); + if (qc && ata_is_ncq(qc->tf.protocol)) { + qc->result_tf.status = status; + qc->result_tf.error = error; + qc->flags |= ATA_QCFLAG_RTF_FILLED; + } + done_mask &= ~(1ULL << tag); + } + + return; + } + + /* + * FBS enabled, so read the status and error for each QC, since the QCs + * can belong to different PMP links. (Each PMP link has its own FIS + * Receive Area.) + */ + while (done_mask) { + struct ata_queued_cmd *qc; + unsigned int tag = __ffs64(done_mask); + + qc = ata_qc_from_tag(ap, tag); + if (qc && ata_is_ncq(qc->tf.protocol)) { + fis = pp->rx_fis; + fis += qc->dev->link->pmp * AHCI_RX_FIS_SZ; + fis += RX_FIS_SDB; + qc->result_tf.status = fis[2]; + qc->result_tf.error = fis[3]; + qc->flags |= ATA_QCFLAG_RTF_FILLED; + } + done_mask &= ~(1ULL << tag); + } } static void ahci_freeze(struct ata_port *ap) @@ -2138,7 +2231,7 @@ static void ahci_post_internal_cmd(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; /* make DMA engine forget about the failed command */ - if (qc->flags & ATA_QCFLAG_FAILED) + if (qc->flags & ATA_QCFLAG_EH) ahci_kick_engine(ap); } diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index c4c89d24f84c..14c17c3bda4e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -552,7 +552,7 @@ static const u8 ata_rw_cmds[] = { 0, 0, 0, - ATA_CMD_WRITE_MULTI_FUA_EXT, + 0, /* pio */ ATA_CMD_PIO_READ, ATA_CMD_PIO_WRITE, @@ -574,17 +574,18 @@ static const u8 ata_rw_cmds[] = { }; /** - * ata_rwcmd_protocol - set taskfile r/w commands and protocol - * @tf: command to examine and configure - * @dev: device tf belongs to + * ata_set_rwcmd_protocol - set taskfile r/w command and protocol + * @dev: target device for the taskfile + * @tf: taskfile to examine and configure * - * Examine the device configuration and tf->flags to calculate - * the proper read/write commands and protocol to use. + * Examine the device configuration and tf->flags to determine + * the proper read/write command and protocol to use for @tf. * * LOCKING: * caller. */ -static int ata_rwcmd_protocol(struct ata_taskfile *tf, struct ata_device *dev) +static bool ata_set_rwcmd_protocol(struct ata_device *dev, + struct ata_taskfile *tf) { u8 cmd; @@ -607,11 +608,12 @@ static int ata_rwcmd_protocol(struct ata_taskfile *tf, struct ata_device *dev) } cmd = ata_rw_cmds[index + fua + lba48 + write]; - if (cmd) { - tf->command = cmd; - return 0; - } - return -1; + if (!cmd) + return false; + + tf->command = cmd; + + return true; } /** @@ -725,7 +727,8 @@ int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, } else if (dev->flags & ATA_DFLAG_LBA) { tf->flags |= ATA_TFLAG_LBA; - if (lba_28_ok(block, n_block)) { + /* We need LBA48 for FUA writes */ + if (!(tf->flags & ATA_TFLAG_FUA) && lba_28_ok(block, n_block)) { /* use LBA28 */ tf->device |= (block >> 24) & 0xf; } else if (lba_48_ok(block, n_block)) { @@ -740,11 +743,12 @@ int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, tf->hob_lbah = (block >> 40) & 0xff; tf->hob_lbam = (block >> 32) & 0xff; tf->hob_lbal = (block >> 24) & 0xff; - } else + } else { /* request too large even for LBA48 */ return -ERANGE; + } - if (unlikely(ata_rwcmd_protocol(tf, dev) < 0)) + if (unlikely(!ata_set_rwcmd_protocol(dev, tf))) return -EINVAL; tf->nsect = n_block & 0xff; @@ -762,7 +766,7 @@ int ata_build_rw_tf(struct ata_queued_cmd *qc, u64 block, u32 n_block, if (!lba_28_ok(block, n_block)) return -ERANGE; - if (unlikely(ata_rwcmd_protocol(tf, dev) < 0)) + if (unlikely(!ata_set_rwcmd_protocol(dev, tf))) return -EINVAL; /* Convert LBA to CHS */ @@ -1590,7 +1594,7 @@ static unsigned ata_exec_internal_sg(struct ata_device *dev, ap->ops->post_internal_cmd(qc); /* perform minimal error analysis */ - if (qc->flags & ATA_QCFLAG_FAILED) { + if (qc->flags & ATA_QCFLAG_EH) { if (qc->result_tf.status & (ATA_ERR | ATA_DF)) qc->err_mask |= AC_ERR_DEV; @@ -2420,6 +2424,28 @@ static void ata_dev_config_chs(struct ata_device *dev) dev->heads, dev->sectors); } +static void ata_dev_config_fua(struct ata_device *dev) +{ + /* Ignore FUA support if its use is disabled globally */ + if (!libata_fua) + goto nofua; + + /* Ignore devices without support for WRITE DMA FUA EXT */ + if (!(dev->flags & ATA_DFLAG_LBA48) || !ata_id_has_fua(dev->id)) + goto nofua; + + /* Ignore known bad devices and devices that lack NCQ support */ + if (!ata_ncq_supported(dev) || (dev->horkage & ATA_HORKAGE_NO_FUA)) + goto nofua; + + dev->flags |= ATA_DFLAG_FUA; + + return; + +nofua: + dev->flags &= ~ATA_DFLAG_FUA; +} + static void ata_dev_config_devslp(struct ata_device *dev) { u8 *sata_setting = dev->link->ap->sector_buf; @@ -2508,7 +2534,8 @@ static void ata_dev_print_features(struct ata_device *dev) return; ata_dev_info(dev, - "Features:%s%s%s%s%s%s\n", + "Features:%s%s%s%s%s%s%s\n", + dev->flags & ATA_DFLAG_FUA ? " FUA" : "", dev->flags & ATA_DFLAG_TRUSTED ? " Trust" : "", dev->flags & ATA_DFLAG_DA ? " Dev-Attention" : "", dev->flags & ATA_DFLAG_DEVSLP ? " Dev-Sleep" : "", @@ -2669,6 +2696,7 @@ int ata_dev_configure(struct ata_device *dev) ata_dev_config_chs(dev); } + ata_dev_config_fua(dev); ata_dev_config_devslp(dev); ata_dev_config_sense_reporting(dev); ata_dev_config_zac(dev); @@ -4106,6 +4134,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { */ { "SATADOM-ML 3ME", NULL, ATA_HORKAGE_NO_LOG_DIR }, + /* Buggy FUA */ + { "Maxtor", "BANC1G10", ATA_HORKAGE_NO_FUA }, + { "WDC*WD2500J*", NULL, ATA_HORKAGE_NO_FUA }, + { "OCZ-VERTEX*", NULL, ATA_HORKAGE_NO_FUA }, + { "INTEL*SSDSC2CT*", NULL, ATA_HORKAGE_NO_FUA }, + /* End Marker */ { } }; @@ -4686,10 +4720,10 @@ void ata_qc_complete(struct ata_queued_cmd *qc) /* XXX: New EH and old EH use different mechanisms to * synchronize EH with regular execution path. * - * In new EH, a failed qc is marked with ATA_QCFLAG_FAILED. + * In new EH, a qc owned by EH is marked with ATA_QCFLAG_EH. * Normal execution path is responsible for not accessing a - * failed qc. libata core enforces the rule by returning NULL - * from ata_qc_from_tag() for failed qcs. + * qc owned by EH. libata core enforces the rule by returning NULL + * from ata_qc_from_tag() for qcs owned by EH. * * Old EH depends on ata_qc_complete() nullifying completion * requests if ATA_QCFLAG_EH_SCHEDULED is set. Old EH does @@ -4701,7 +4735,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) struct ata_eh_info *ehi = &dev->link->eh_info; if (unlikely(qc->err_mask)) - qc->flags |= ATA_QCFLAG_FAILED; + qc->flags |= ATA_QCFLAG_EH; /* * Finish internal commands without any further processing @@ -4718,7 +4752,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc) * Non-internal qc has failed. Fill the result TF and * summon EH. */ - if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) { + if (unlikely(qc->flags & ATA_QCFLAG_EH)) { fill_result_tf(qc); trace_ata_qc_complete_failed(qc); ata_qc_schedule_eh(qc); @@ -6217,6 +6251,7 @@ static const struct ata_force_param force_tbl[] __initconst = { force_horkage_onoff(lpm, ATA_HORKAGE_NOLPM), force_horkage_onoff(setxfer, ATA_HORKAGE_NOSETXFER), force_horkage_on(dump_id, ATA_HORKAGE_DUMP_ID), + force_horkage_onoff(fua, ATA_HORKAGE_NO_FUA), force_horkage_on(disable, ATA_HORKAGE_DISABLE), }; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 34303ce67c14..a6c901811802 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -565,17 +565,23 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, { int i; unsigned long flags; + struct scsi_cmnd *scmd, *tmp; + int nr_timedout = 0; /* make sure sff pio task is not running */ ata_sff_flush_pio_task(ap); + if (!ap->ops->error_handler) + return; + /* synchronize with host lock and sort out timeouts */ - /* For new EH, all qcs are finished in one of three ways - + /* + * For new EH, all qcs are finished in one of three ways - * normal completion, error completion, and SCSI timeout. * Both completions can race against SCSI timeout. When normal * completion wins, the qc never reaches EH. When error - * completion wins, the qc has ATA_QCFLAG_FAILED set. + * completion wins, the qc has ATA_QCFLAG_EH set. * * When SCSI timeout wins, things are a bit more complex. * Normal or error completion can occur after the timeout but @@ -584,64 +590,61 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, * timed out iff its associated qc is active and not failed. */ spin_lock_irqsave(ap->lock, flags); - if (ap->ops->error_handler) { - struct scsi_cmnd *scmd, *tmp; - int nr_timedout = 0; - - /* This must occur under the ap->lock as we don't want - a polled recovery to race the real interrupt handler - - The lost_interrupt handler checks for any completed but - non-notified command and completes much like an IRQ handler. - We then fall into the error recovery code which will treat - this as if normal completion won the race */ - - if (ap->ops->lost_interrupt) - ap->ops->lost_interrupt(ap); + /* + * This must occur under the ap->lock as we don't want + * a polled recovery to race the real interrupt handler + * + * The lost_interrupt handler checks for any completed but + * non-notified command and completes much like an IRQ handler. + * + * We then fall into the error recovery code which will treat + * this as if normal completion won the race + */ + if (ap->ops->lost_interrupt) + ap->ops->lost_interrupt(ap); - list_for_each_entry_safe(scmd, tmp, eh_work_q, eh_entry) { - struct ata_queued_cmd *qc; + list_for_each_entry_safe(scmd, tmp, eh_work_q, eh_entry) { + struct ata_queued_cmd *qc; - ata_qc_for_each_raw(ap, qc, i) { - if (qc->flags & ATA_QCFLAG_ACTIVE && - qc->scsicmd == scmd) - break; - } + ata_qc_for_each_raw(ap, qc, i) { + if (qc->flags & ATA_QCFLAG_ACTIVE && + qc->scsicmd == scmd) + break; + } - if (i < ATA_MAX_QUEUE) { - /* the scmd has an associated qc */ - if (!(qc->flags & ATA_QCFLAG_FAILED)) { - /* which hasn't failed yet, timeout */ - qc->err_mask |= AC_ERR_TIMEOUT; - qc->flags |= ATA_QCFLAG_FAILED; - nr_timedout++; - } - } else { - /* Normal completion occurred after - * SCSI timeout but before this point. - * Successfully complete it. - */ - scmd->retries = scmd->allowed; - scsi_eh_finish_cmd(scmd, &ap->eh_done_q); + if (i < ATA_MAX_QUEUE) { + /* the scmd has an associated qc */ + if (!(qc->flags & ATA_QCFLAG_EH)) { + /* which hasn't failed yet, timeout */ + qc->err_mask |= AC_ERR_TIMEOUT; + qc->flags |= ATA_QCFLAG_EH; + nr_timedout++; } + } else { + /* Normal completion occurred after + * SCSI timeout but before this point. + * Successfully complete it. + */ + scmd->retries = scmd->allowed; + scsi_eh_finish_cmd(scmd, &ap->eh_done_q); } + } - /* If we have timed out qcs. They belong to EH from - * this point but the state of the controller is - * unknown. Freeze the port to make sure the IRQ - * handler doesn't diddle with those qcs. This must - * be done atomically w.r.t. setting QCFLAG_FAILED. - */ - if (nr_timedout) - __ata_port_freeze(ap); + /* + * If we have timed out qcs. They belong to EH from + * this point but the state of the controller is + * unknown. Freeze the port to make sure the IRQ + * handler doesn't diddle with those qcs. This must + * be done atomically w.r.t. setting ATA_QCFLAG_EH. + */ + if (nr_timedout) + __ata_port_freeze(ap); + /* initialize eh_tries */ + ap->eh_tries = ATA_EH_MAX_TRIES; - /* initialize eh_tries */ - ap->eh_tries = ATA_EH_MAX_TRIES; - } spin_unlock_irqrestore(ap->lock, flags); - } EXPORT_SYMBOL(ata_scsi_cmd_error_handler); @@ -911,12 +914,12 @@ void ata_qc_schedule_eh(struct ata_queued_cmd *qc) WARN_ON(!ap->ops->error_handler); - qc->flags |= ATA_QCFLAG_FAILED; + qc->flags |= ATA_QCFLAG_EH; ata_eh_set_pending(ap, 1); /* The following will fail if timeout has already expired. * ata_scsi_error() takes care of such scmds on EH entry. - * Note that ATA_QCFLAG_FAILED is unconditionally set after + * Note that ATA_QCFLAG_EH is unconditionally set after * this function completes. */ blk_abort_request(scsi_cmd_to_rq(qc->scsicmd)); @@ -994,7 +997,7 @@ static int ata_do_link_abort(struct ata_port *ap, struct ata_link *link) /* include internal tag in iteration */ ata_qc_for_each_with_internal(ap, qc, tag) { if (qc && (!link || qc->dev->link == link)) { - qc->flags |= ATA_QCFLAG_FAILED; + qc->flags |= ATA_QCFLAG_EH; ata_qc_complete(qc); nr_aborted++; } @@ -1954,7 +1957,7 @@ static void ata_eh_link_autopsy(struct ata_link *link) all_err_mask |= ehc->i.err_mask; ata_qc_for_each_raw(ap, qc, tag) { - if (!(qc->flags & ATA_QCFLAG_FAILED) || + if (!(qc->flags & ATA_QCFLAG_EH) || qc->flags & ATA_QCFLAG_RETRY || ata_dev_phys_link(qc->dev) != link) continue; @@ -2232,7 +2235,7 @@ static void ata_eh_link_report(struct ata_link *link) desc = ehc->i.desc; ata_qc_for_each_raw(ap, qc, tag) { - if (!(qc->flags & ATA_QCFLAG_FAILED) || + if (!(qc->flags & ATA_QCFLAG_EH) || ata_dev_phys_link(qc->dev) != link || ((qc->flags & ATA_QCFLAG_QUIET) && qc->err_mask == AC_ERR_DEV)) @@ -2298,7 +2301,7 @@ static void ata_eh_link_report(struct ata_link *link) char data_buf[20] = ""; char cdb_buf[70] = ""; - if (!(qc->flags & ATA_QCFLAG_FAILED) || + if (!(qc->flags & ATA_QCFLAG_EH) || ata_dev_phys_link(qc->dev) != link || !qc->err_mask) continue; @@ -3802,7 +3805,7 @@ void ata_eh_finish(struct ata_port *ap) /* retry or finish qcs */ ata_qc_for_each_raw(ap, qc, tag) { - if (!(qc->flags & ATA_QCFLAG_FAILED)) + if (!(qc->flags & ATA_QCFLAG_EH)) continue; if (qc->err_mask) { diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index 18ef14e749a0..f3e7396e3191 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -655,6 +655,9 @@ int ata_qc_complete_multiple(struct ata_port *ap, u64 qc_active) return -EINVAL; } + if (ap->ops->qc_ncq_fill_rtf) + ap->ops->qc_ncq_fill_rtf(ap, done_mask); + while (done_mask) { struct ata_queued_cmd *qc; unsigned int tag = __ffs64(done_mask); @@ -1429,7 +1432,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) /* has LLDD analyzed already? */ ata_qc_for_each_raw(ap, qc, tag) { - if (!(qc->flags & ATA_QCFLAG_FAILED)) + if (!(qc->flags & ATA_QCFLAG_EH)) continue; if (qc->err_mask) @@ -1477,7 +1480,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link) } ata_qc_for_each_raw(ap, qc, tag) { - if (!(qc->flags & ATA_QCFLAG_FAILED) || + if (!(qc->flags & ATA_QCFLAG_EH) || ata_dev_phys_link(qc->dev) != link) continue; diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index cbb3a7a50816..aa338f10cef2 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1654,7 +1654,8 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; struct scsi_cmnd *cmd = qc->scsicmd; u8 *cdb = cmd->cmnd; - int need_sense = (qc->err_mask != 0); + int need_sense = (qc->err_mask != 0) && + !(qc->flags & ATA_QCFLAG_SENSE_VALID); /* For ATA pass thru (SAT) commands, generate a sense block if * user mandated it or if there's an error. Note that if we @@ -1668,12 +1669,11 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) if (((cdb[0] == ATA_16) || (cdb[0] == ATA_12)) && ((cdb[2] & 0x20) || need_sense)) ata_gen_passthru_sense(qc); - else if (qc->flags & ATA_QCFLAG_SENSE_VALID) - cmd->result = SAM_STAT_CHECK_CONDITION; else if (need_sense) ata_gen_ata_sense(qc); else - cmd->result = SAM_STAT_GOOD; + /* Keep the SCSI ML and status byte, clear host byte. */ + cmd->result &= 0x0000ffff; if (need_sense && !ap->ops->error_handler) ata_dump_status(ap, &qc->result_tf); @@ -2240,30 +2240,6 @@ static unsigned int ata_msense_rw_recovery(u8 *buf, bool changeable) return sizeof(def_rw_recovery_mpage); } -/* - * We can turn this into a real blacklist if it's needed, for now just - * blacklist any Maxtor BANC1G10 revision firmware - */ -static int ata_dev_supports_fua(u16 *id) -{ - unsigned char model[ATA_ID_PROD_LEN + 1], fw[ATA_ID_FW_REV_LEN + 1]; - - if (!libata_fua) - return 0; - if (!ata_id_has_fua(id)) - return 0; - - ata_id_c_string(id, model, ATA_ID_PROD, sizeof(model)); - ata_id_c_string(id, fw, ATA_ID_FW_REV, sizeof(fw)); - - if (strcmp(model, "Maxtor")) - return 1; - if (strcmp(fw, "BANC1G10")) - return 1; - - return 0; /* blacklisted */ -} - /** * ata_scsiop_mode_sense - Simulate MODE SENSE 6, 10 commands * @args: device IDENTIFY data / SCSI command of interest. @@ -2287,7 +2263,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) }; u8 pg, spg; unsigned int ebd, page_control, six_byte; - u8 dpofua, bp = 0xff; + u8 dpofua = 0, bp = 0xff; u16 fp; six_byte = (scsicmd[0] == MODE_SENSE); @@ -2350,9 +2326,7 @@ static unsigned int ata_scsiop_mode_sense(struct ata_scsi_args *args, u8 *rbuf) goto invalid_fld; } - dpofua = 0; - if (ata_dev_supports_fua(args->id) && (dev->flags & ATA_DFLAG_LBA48) && - (!(dev->flags & ATA_DFLAG_PIO) || dev->multi_count)) + if (dev->flags & ATA_DFLAG_FUA) dpofua = 1 << 4; if (six_byte) { @@ -3266,11 +3240,12 @@ static unsigned int ata_scsiop_maint_in(struct ata_scsi_args *args, u8 *rbuf) u8 supported = 0; unsigned int err = 0; - if (cdb[2] != 1) { + if (cdb[2] != 1 && cdb[2] != 3) { ata_dev_warn(dev, "invalid command format %d\n", cdb[2]); err = 2; goto out; } + switch (cdb[3]) { case INQUIRY: case MODE_SENSE: diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 153f49e00713..cd82d3b5ed14 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -1377,14 +1377,10 @@ EXPORT_SYMBOL_GPL(ata_sff_qc_issue); * * LOCKING: * spin_lock_irqsave(host lock) - * - * RETURNS: - * true indicating that result TF is successfully filled. */ -bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc) +void ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc) { qc->ap->ops->sff_tf_read(qc->ap, &qc->result_tf); - return true; } EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf); @@ -2073,7 +2069,7 @@ void ata_sff_error_handler(struct ata_port *ap) unsigned long flags; qc = __ata_qc_from_tag(ap, ap->link.active_tag); - if (qc && !(qc->flags & ATA_QCFLAG_FAILED)) + if (qc && !(qc->flags & ATA_QCFLAG_EH)) qc = NULL; spin_lock_irqsave(ap->lock, flags); @@ -2796,7 +2792,7 @@ void ata_bmdma_error_handler(struct ata_port *ap) bool thaw = false; qc = __ata_qc_from_tag(ap, ap->link.active_tag); - if (qc && !(qc->flags & ATA_QCFLAG_FAILED)) + if (qc && !(qc->flags & ATA_QCFLAG_EH)) qc = NULL; /* reset PIO HSM and stop DMA engine */ diff --git a/drivers/ata/libata-trace.c b/drivers/ata/libata-trace.c index e0e4d0d5a100..9b5363fd0ab0 100644 --- a/drivers/ata/libata-trace.c +++ b/drivers/ata/libata-trace.c @@ -142,7 +142,7 @@ libata_trace_parse_qc_flags(struct trace_seq *p, unsigned int qc_flags) trace_seq_printf(p, "QUIET "); if (qc_flags & ATA_QCFLAG_RETRY) trace_seq_printf(p, "RETRY "); - if (qc_flags & ATA_QCFLAG_FAILED) + if (qc_flags & ATA_QCFLAG_EH) trace_seq_printf(p, "FAILED "); if (qc_flags & ATA_QCFLAG_SENSE_VALID) trace_seq_printf(p, "SENSE_VALID "); diff --git a/drivers/ata/pata_parport/Kconfig b/drivers/ata/pata_parport/Kconfig new file mode 100644 index 000000000000..0893a13e7979 --- /dev/null +++ b/drivers/ata/pata_parport/Kconfig @@ -0,0 +1,141 @@ +# SPDX-License-Identifier: GPL-2.0 + +comment "Parallel IDE protocol modules" + depends on PATA_PARPORT + +config PATA_PARPORT_ATEN + tristate "ATEN EH-100 protocol" + depends on PATA_PARPORT + help + This option enables support for the ATEN EH-100 parallel port IDE + protocol. This protocol is used in some inexpensive low performance + parallel port kits made in Hong Kong. + +config PATA_PARPORT_BPCK + tristate "MicroSolutions backpack (Series 5) protocol" + depends on PATA_PARPORT + help + This option enables support for the Micro Solutions BACKPACK + parallel port Series 5 IDE protocol. (Most BACKPACK drives made + before 1999 were Series 5) Series 5 drives will NOT always have the + Series noted on the bottom of the drive. Series 6 drivers will. + + In other words, if your BACKPACK drive doesn't say "Series 6" on the + bottom, enable this option. + +config PATA_PARPORT_BPCK6 + tristate "MicroSolutions backpack (Series 6) protocol" + depends on (PATA_PARPORT) && !64BIT + help + This option enables support for the Micro Solutions BACKPACK + parallel port Series 6 IDE protocol. (Most BACKPACK drives made + after 1999 were Series 6) Series 6 drives will have the Series noted + on the bottom of the drive. Series 5 drivers don't always have it + noted. + + In other words, if your BACKPACK drive says "Series 6" on the + bottom, enable this option. + +config PATA_PARPORT_COMM + tristate "DataStor Commuter protocol" + depends on PATA_PARPORT + help + This option enables support for the Commuter parallel port IDE + protocol from DataStor. + +config PATA_PARPORT_DSTR + tristate "DataStor EP-2000 protocol" + depends on PATA_PARPORT + help + This option enables support for the EP-2000 parallel port IDE + protocol from DataStor + +config PATA_PARPORT_FIT2 + tristate "FIT TD-2000 protocol" + depends on PATA_PARPORT + help + This option enables support for the TD-2000 parallel port IDE + protocol from Fidelity International Technology. This is a simple + (low speed) adapter that is used in some portable hard drives. + +config PATA_PARPORT_FIT3 + tristate "FIT TD-3000 protocol" + depends on PATA_PARPORT + help + This option enables support for the TD-3000 parallel port IDE + protocol from Fidelity International Technology. This protocol is + used in newer models of their portable disk, CD-ROM and PD/CD + devices. + +config PATA_PARPORT_EPAT + tristate "Shuttle EPAT/EPEZ protocol" + depends on PATA_PARPORT + help + This option enables support for the EPAT parallel port IDE protocol. + EPAT is a parallel port IDE adapter manufactured by Shuttle + Technology and widely used in devices from major vendors such as + Hewlett-Packard, SyQuest, Imation and Avatar. + +config PATA_PARPORT_EPATC8 + bool "Support c7/c8 chips" + depends on PATA_PARPORT_EPAT + help + This option enables support for the newer Shuttle EP1284 (aka c7 and + c8) chip. You need this if you are using any recent Imation SuperDisk + (LS-120) drive. + +config PATA_PARPORT_EPIA + tristate "Shuttle EPIA protocol" + depends on PATA_PARPORT + help + This option enables support for the (obsolete) EPIA parallel port + IDE protocol from Shuttle Technology. This adapter can still be + found in some no-name kits. + +config PATA_PARPORT_FRIQ + tristate "Freecom IQ ASIC-2 protocol" + depends on PATA_PARPORT + help + This option enables support for version 2 of the Freecom IQ parallel + port IDE adapter. This adapter is used by the Maxell Superdisk + drive. + +config PATA_PARPORT_FRPW + tristate "FreeCom power protocol" + depends on PATA_PARPORT + help + This option enables support for the Freecom power parallel port IDE + protocol. + +config PATA_PARPORT_KBIC + tristate "KingByte KBIC-951A/971A protocols" + depends on PATA_PARPORT + help + This option enables support for the KBIC-951A and KBIC-971A parallel + port IDE protocols from KingByte Information Corp. KingByte's + adapters appear in many no-name portable disk and CD-ROM products, + especially in Europe. + +config PATA_PARPORT_KTTI + tristate "KT PHd protocol" + depends on PATA_PARPORT + help + This option enables support for the "PHd" parallel port IDE protocol + from KT Technology. This is a simple (low speed) adapter that is + used in some 2.5" portable hard drives. + +config PATA_PARPORT_ON20 + tristate "OnSpec 90c20 protocol" + depends on PATA_PARPORT + help + This option enables support for the (obsolete) 90c20 parallel port + IDE protocol from OnSpec (often marketed under the ValuStore brand + name). + +config PATA_PARPORT_ON26 + tristate "OnSpec 90c26 protocol" + depends on PATA_PARPORT + help + This option enables support for the 90c26 parallel port IDE protocol + from OnSpec Electronics (often marketed under the ValuStore brand + name). diff --git a/drivers/ata/pata_parport/Makefile b/drivers/ata/pata_parport/Makefile new file mode 100644 index 000000000000..0932c8d55b91 --- /dev/null +++ b/drivers/ata/pata_parport/Makefile @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_PATA_PARPORT) += pata_parport.o + +obj-$(CONFIG_PATA_PARPORT_ATEN) += aten.o +obj-$(CONFIG_PATA_PARPORT_BPCK) += bpck.o +obj-$(CONFIG_PATA_PARPORT_COMM) += comm.o +obj-$(CONFIG_PATA_PARPORT_DSTR) += dstr.o +obj-$(CONFIG_PATA_PARPORT_KBIC) += kbic.o +obj-$(CONFIG_PATA_PARPORT_EPAT) += epat.o +obj-$(CONFIG_PATA_PARPORT_EPIA) += epia.o +obj-$(CONFIG_PATA_PARPORT_FRPW) += frpw.o +obj-$(CONFIG_PATA_PARPORT_FRIQ) += friq.o +obj-$(CONFIG_PATA_PARPORT_FIT2) += fit2.o +obj-$(CONFIG_PATA_PARPORT_FIT3) += fit3.o +obj-$(CONFIG_PATA_PARPORT_ON20) += on20.o +obj-$(CONFIG_PATA_PARPORT_ON26) += on26.o +obj-$(CONFIG_PATA_PARPORT_KTTI) += ktti.o +obj-$(CONFIG_PATA_PARPORT_BPCK6) += bpck6.o diff --git a/drivers/block/paride/aten.c b/drivers/ata/pata_parport/aten.c index 2695465568ad..b66508bedbd0 100644 --- a/drivers/block/paride/aten.c +++ b/drivers/ata/pata_parport/aten.c @@ -25,7 +25,7 @@ #include <linux/types.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> #define j44(a,b) ((((a>>4)&0x0f)|(b&0xf0))^0x88) diff --git a/drivers/block/paride/bpck.c b/drivers/ata/pata_parport/bpck.c index d880a9465e9b..5fb3cf9ba11d 100644 --- a/drivers/block/paride/bpck.c +++ b/drivers/ata/pata_parport/bpck.c @@ -24,7 +24,7 @@ #include <linux/wait.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> #undef r2 #undef w2 diff --git a/drivers/block/paride/bpck6.c b/drivers/ata/pata_parport/bpck6.c index ec64e7f5d1ce..d897e2a28efe 100644 --- a/drivers/block/paride/bpck6.c +++ b/drivers/ata/pata_parport/bpck6.c @@ -31,7 +31,7 @@ #include <linux/parport.h> #include "ppc6lnx.c" -#include "paride.h" +#include <linux/pata_parport.h> /* PARAMETERS */ static bool verbose; /* set this to 1 to see debugging messages and whatnot */ diff --git a/drivers/block/paride/comm.c b/drivers/ata/pata_parport/comm.c index 9bcd35495323..1775e7ed9336 100644 --- a/drivers/block/paride/comm.c +++ b/drivers/ata/pata_parport/comm.c @@ -24,7 +24,7 @@ #include <linux/wait.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> /* mode codes: 0 nybble reads, 8-bit writes 1 8-bit reads and writes diff --git a/drivers/block/paride/dstr.c b/drivers/ata/pata_parport/dstr.c index accc5c777cbb..edf414d186a6 100644 --- a/drivers/block/paride/dstr.c +++ b/drivers/ata/pata_parport/dstr.c @@ -23,7 +23,7 @@ #include <linux/wait.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> /* mode codes: 0 nybble reads, 8-bit writes 1 8-bit reads and writes diff --git a/drivers/block/paride/epat.c b/drivers/ata/pata_parport/epat.c index 1bcdff77322e..6ce2dee7657f 100644 --- a/drivers/block/paride/epat.c +++ b/drivers/ata/pata_parport/epat.c @@ -26,7 +26,7 @@ #include <linux/wait.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> #define j44(a,b) (((a>>4)&0x0f)+(b&0xf0)) #define j53(a,b) (((a>>3)&0x1f)+((b<<4)&0xe0)) diff --git a/drivers/block/paride/epia.c b/drivers/ata/pata_parport/epia.c index fb0e782d055e..417d5a3c7f72 100644 --- a/drivers/block/paride/epia.c +++ b/drivers/ata/pata_parport/epia.c @@ -27,7 +27,7 @@ #include <linux/wait.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> /* mode codes: 0 nybble reads on port 1, 8-bit writes 1 5/3 reads on ports 1 & 2, 8-bit writes diff --git a/drivers/block/paride/fit2.c b/drivers/ata/pata_parport/fit2.c index 381283753ae4..3c7a1069b026 100644 --- a/drivers/block/paride/fit2.c +++ b/drivers/ata/pata_parport/fit2.c @@ -23,7 +23,7 @@ #include <linux/wait.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> #define j44(a,b) (((a>>4)&0x0f)|(b&0xf0)) diff --git a/drivers/block/paride/fit3.c b/drivers/ata/pata_parport/fit3.c index 275d269458eb..cd95f4f0edc2 100644 --- a/drivers/block/paride/fit3.c +++ b/drivers/ata/pata_parport/fit3.c @@ -27,7 +27,7 @@ #include <linux/wait.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> #define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0)) diff --git a/drivers/block/paride/friq.c b/drivers/ata/pata_parport/friq.c index 4f2ba244689b..da1d0cb016d6 100644 --- a/drivers/block/paride/friq.c +++ b/drivers/ata/pata_parport/friq.c @@ -35,7 +35,7 @@ #include <linux/wait.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> #define CMD(x) w2(4);w0(0xff);w0(0xff);w0(0x73);w0(0x73);\ w0(0xc9);w0(0xc9);w0(0x26);w0(0x26);w0(x);w0(x); diff --git a/drivers/block/paride/frpw.c b/drivers/ata/pata_parport/frpw.c index c3cde364603a..7bc8fa16d5d8 100644 --- a/drivers/block/paride/frpw.c +++ b/drivers/ata/pata_parport/frpw.c @@ -33,7 +33,7 @@ #include <linux/wait.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> #define cec4 w2(0xc);w2(0xe);w2(0xe);w2(0xc);w2(4);w2(4);w2(4); #define j44(l,h) (((l>>4)&0x0f)|(h&0xf0)) diff --git a/drivers/block/paride/kbic.c b/drivers/ata/pata_parport/kbic.c index 35999c415ee3..f0960eb68635 100644 --- a/drivers/block/paride/kbic.c +++ b/drivers/ata/pata_parport/kbic.c @@ -28,7 +28,7 @@ #include <linux/wait.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> #define r12w() (delay_p,inw(pi->port+1)&0xffff) diff --git a/drivers/block/paride/ktti.c b/drivers/ata/pata_parport/ktti.c index 117ab0e8ccf0..fc4f707fed1f 100644 --- a/drivers/block/paride/ktti.c +++ b/drivers/ata/pata_parport/ktti.c @@ -19,7 +19,7 @@ #include <linux/wait.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> #define j44(a,b) (((a>>4)&0x0f)|(b&0xf0)) diff --git a/drivers/block/paride/on20.c b/drivers/ata/pata_parport/on20.c index 0173697a1a4d..995fc41e3122 100644 --- a/drivers/block/paride/on20.c +++ b/drivers/ata/pata_parport/on20.c @@ -22,7 +22,7 @@ #include <linux/wait.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> #define op(f) w2(4);w0(f);w2(5);w2(0xd);w2(5);w2(0xd);w2(5);w2(4); #define vl(v) w2(4);w0(v);w2(5);w2(7);w2(5);w2(4); diff --git a/drivers/block/paride/on26.c b/drivers/ata/pata_parport/on26.c index 95ba256921f2..35f1c481a782 100644 --- a/drivers/block/paride/on26.c +++ b/drivers/ata/pata_parport/on26.c @@ -26,7 +26,7 @@ #include <linux/wait.h> #include <asm/io.h> -#include "paride.h" +#include <linux/pata_parport.h> /* mode codes: 0 nybble reads, 8-bit writes 1 8-bit reads and writes diff --git a/drivers/ata/pata_parport/pata_parport.c b/drivers/ata/pata_parport/pata_parport.c new file mode 100644 index 000000000000..294a266a0dda --- /dev/null +++ b/drivers/ata/pata_parport/pata_parport.c @@ -0,0 +1,761 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright 2023 Ondrej Zary + * based on paride.c by Grant R. Guenther <grant@torque.net> + */ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/parport.h> +#include <linux/pata_parport.h> + +#define DRV_NAME "pata_parport" + +static DEFINE_IDR(parport_list); +static DEFINE_IDR(protocols); +static DEFINE_IDA(pata_parport_bus_dev_ids); +static DEFINE_MUTEX(pi_mutex); + +static bool probe = true; +module_param(probe, bool, 0644); +MODULE_PARM_DESC(probe, "Enable automatic device probing (0=off, 1=on [default])"); + +/* + * libata drivers cannot sleep so this driver claims parport before activating + * the ata host and keeps it claimed (and protocol connected) until the ata + * host is removed. Unfortunately, this means that you cannot use any chained + * devices (neither other pata_parport devices nor a printer). + */ +static void pi_connect(struct pi_adapter *pi) +{ + parport_claim_or_block(pi->pardev); + pi->proto->connect(pi); +} + +static void pi_disconnect(struct pi_adapter *pi) +{ + pi->proto->disconnect(pi); + parport_release(pi->pardev); +} + +static void pata_parport_dev_select(struct ata_port *ap, unsigned int device) +{ + struct pi_adapter *pi = ap->host->private_data; + u8 tmp; + + if (device == 0) + tmp = ATA_DEVICE_OBS; + else + tmp = ATA_DEVICE_OBS | ATA_DEV1; + + pi->proto->write_regr(pi, 0, ATA_REG_DEVICE, tmp); + ata_sff_pause(ap); +} + +static bool pata_parport_devchk(struct ata_port *ap, unsigned int device) +{ + struct pi_adapter *pi = ap->host->private_data; + u8 nsect, lbal; + + pata_parport_dev_select(ap, device); + + pi->proto->write_regr(pi, 0, ATA_REG_NSECT, 0x55); + pi->proto->write_regr(pi, 0, ATA_REG_LBAL, 0xaa); + + pi->proto->write_regr(pi, 0, ATA_REG_NSECT, 0xaa); + pi->proto->write_regr(pi, 0, ATA_REG_LBAL, 0x55); + + pi->proto->write_regr(pi, 0, ATA_REG_NSECT, 055); + pi->proto->write_regr(pi, 0, ATA_REG_LBAL, 0xaa); + + nsect = pi->proto->read_regr(pi, 0, ATA_REG_NSECT); + lbal = pi->proto->read_regr(pi, 0, ATA_REG_LBAL); + + return (nsect == 0x55) && (lbal == 0xaa); +} + +static int pata_parport_bus_softreset(struct ata_port *ap, unsigned int devmask, + unsigned long deadline) +{ + struct pi_adapter *pi = ap->host->private_data; + + /* software reset. causes dev0 to be selected */ + pi->proto->write_regr(pi, 1, 6, ap->ctl); + udelay(20); + pi->proto->write_regr(pi, 1, 6, ap->ctl | ATA_SRST); + udelay(20); + pi->proto->write_regr(pi, 1, 6, ap->ctl); + ap->last_ctl = ap->ctl; + + /* wait the port to become ready */ + return ata_sff_wait_after_reset(&ap->link, devmask, deadline); +} + +static int pata_parport_softreset(struct ata_link *link, unsigned int *classes, + unsigned long deadline) +{ + struct ata_port *ap = link->ap; + unsigned int devmask = 0; + int rc; + u8 err; + + /* determine if device 0/1 are present */ + if (pata_parport_devchk(ap, 0)) + devmask |= (1 << 0); + if (pata_parport_devchk(ap, 1)) + devmask |= (1 << 1); + + /* select device 0 again */ + pata_parport_dev_select(ap, 0); + + /* issue bus reset */ + rc = pata_parport_bus_softreset(ap, devmask, deadline); + if (rc && rc != -ENODEV) { + ata_link_err(link, "SRST failed (errno=%d)\n", rc); + return rc; + } + + /* determine by signature whether we have ATA or ATAPI devices */ + classes[0] = ata_sff_dev_classify(&link->device[0], + devmask & (1 << 0), &err); + if (err != 0x81) + classes[1] = ata_sff_dev_classify(&link->device[1], + devmask & (1 << 1), &err); + + return 0; +} + +static u8 pata_parport_check_status(struct ata_port *ap) +{ + struct pi_adapter *pi = ap->host->private_data; + + return pi->proto->read_regr(pi, 0, ATA_REG_STATUS); +} + +static u8 pata_parport_check_altstatus(struct ata_port *ap) +{ + struct pi_adapter *pi = ap->host->private_data; + + return pi->proto->read_regr(pi, 1, 6); +} + +static void pata_parport_tf_load(struct ata_port *ap, + const struct ata_taskfile *tf) +{ + struct pi_adapter *pi = ap->host->private_data; + + if (tf->ctl != ap->last_ctl) { + pi->proto->write_regr(pi, 1, 6, tf->ctl); + ap->last_ctl = tf->ctl; + ata_wait_idle(ap); + } + + if (tf->flags & ATA_TFLAG_ISADDR) { + if (tf->flags & ATA_TFLAG_LBA48) { + pi->proto->write_regr(pi, 0, ATA_REG_FEATURE, + tf->hob_feature); + pi->proto->write_regr(pi, 0, ATA_REG_NSECT, + tf->hob_nsect); + pi->proto->write_regr(pi, 0, ATA_REG_LBAL, + tf->hob_lbal); + pi->proto->write_regr(pi, 0, ATA_REG_LBAM, + tf->hob_lbam); + pi->proto->write_regr(pi, 0, ATA_REG_LBAH, + tf->hob_lbah); + } + pi->proto->write_regr(pi, 0, ATA_REG_FEATURE, tf->feature); + pi->proto->write_regr(pi, 0, ATA_REG_NSECT, tf->nsect); + pi->proto->write_regr(pi, 0, ATA_REG_LBAL, tf->lbal); + pi->proto->write_regr(pi, 0, ATA_REG_LBAM, tf->lbam); + pi->proto->write_regr(pi, 0, ATA_REG_LBAH, tf->lbah); + } + + if (tf->flags & ATA_TFLAG_DEVICE) + pi->proto->write_regr(pi, 0, ATA_REG_DEVICE, tf->device); + + ata_wait_idle(ap); +} + +static void pata_parport_tf_read(struct ata_port *ap, struct ata_taskfile *tf) +{ + struct pi_adapter *pi = ap->host->private_data; + + tf->status = pi->proto->read_regr(pi, 0, ATA_REG_STATUS); + tf->error = pi->proto->read_regr(pi, 0, ATA_REG_ERR); + tf->nsect = pi->proto->read_regr(pi, 0, ATA_REG_NSECT); + tf->lbal = pi->proto->read_regr(pi, 0, ATA_REG_LBAL); + tf->lbam = pi->proto->read_regr(pi, 0, ATA_REG_LBAM); + tf->lbah = pi->proto->read_regr(pi, 0, ATA_REG_LBAH); + tf->device = pi->proto->read_regr(pi, 0, ATA_REG_DEVICE); + + if (tf->flags & ATA_TFLAG_LBA48) { + pi->proto->write_regr(pi, 1, 6, tf->ctl | ATA_HOB); + tf->hob_feature = pi->proto->read_regr(pi, 0, ATA_REG_ERR); + tf->hob_nsect = pi->proto->read_regr(pi, 0, ATA_REG_NSECT); + tf->hob_lbal = pi->proto->read_regr(pi, 0, ATA_REG_LBAL); + tf->hob_lbam = pi->proto->read_regr(pi, 0, ATA_REG_LBAM); + tf->hob_lbah = pi->proto->read_regr(pi, 0, ATA_REG_LBAH); + pi->proto->write_regr(pi, 1, 6, tf->ctl); + ap->last_ctl = tf->ctl; + } +} + +static void pata_parport_exec_command(struct ata_port *ap, + const struct ata_taskfile *tf) +{ + struct pi_adapter *pi = ap->host->private_data; + + pi->proto->write_regr(pi, 0, ATA_REG_CMD, tf->command); + ata_sff_pause(ap); +} + +static unsigned int pata_parport_data_xfer(struct ata_queued_cmd *qc, + unsigned char *buf, unsigned int buflen, int rw) +{ + struct ata_port *ap = qc->dev->link->ap; + struct pi_adapter *pi = ap->host->private_data; + + if (rw == READ) + pi->proto->read_block(pi, buf, buflen); + else + pi->proto->write_block(pi, buf, buflen); + + return buflen; +} + +static void pata_parport_drain_fifo(struct ata_queued_cmd *qc) +{ + int count; + struct ata_port *ap; + struct pi_adapter *pi; + char junk[2]; + + /* We only need to flush incoming data when a command was running */ + if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE) + return; + + ap = qc->ap; + pi = ap->host->private_data; + /* Drain up to 64K of data before we give up this recovery method */ + for (count = 0; (pata_parport_check_status(ap) & ATA_DRQ) + && count < 65536; count += 2) { + pi->proto->read_block(pi, junk, 2); + } + + if (count) + ata_port_dbg(ap, "drained %d bytes to clear DRQ\n", count); +} + +static struct ata_port_operations pata_parport_port_ops = { + .inherits = &ata_sff_port_ops, + + .softreset = pata_parport_softreset, + .hardreset = NULL, + + .sff_dev_select = pata_parport_dev_select, + .sff_check_status = pata_parport_check_status, + .sff_check_altstatus = pata_parport_check_altstatus, + .sff_tf_load = pata_parport_tf_load, + .sff_tf_read = pata_parport_tf_read, + .sff_exec_command = pata_parport_exec_command, + .sff_data_xfer = pata_parport_data_xfer, + .sff_drain_fifo = pata_parport_drain_fifo, +}; + +static const struct ata_port_info pata_parport_port_info = { + .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_POLLING, + .pio_mask = ATA_PIO0, + /* No DMA */ + .port_ops = &pata_parport_port_ops, +}; + +static void pi_release(struct pi_adapter *pi) +{ + parport_unregister_device(pi->pardev); + if (pi->proto->release_proto) + pi->proto->release_proto(pi); + module_put(pi->proto->owner); +} + +static int default_test_proto(struct pi_adapter *pi, char *scratch) +{ + int j, k; + int e[2] = { 0, 0 }; + + pi->proto->connect(pi); + + for (j = 0; j < 2; j++) { + pi->proto->write_regr(pi, 0, 6, 0xa0 + j * 0x10); + for (k = 0; k < 256; k++) { + pi->proto->write_regr(pi, 0, 2, k ^ 0xaa); + pi->proto->write_regr(pi, 0, 3, k ^ 0x55); + if (pi->proto->read_regr(pi, 0, 2) != (k ^ 0xaa)) + e[j]++; + } + } + pi->proto->disconnect(pi); + + dev_dbg(&pi->dev, "%s: port 0x%x, mode %d, test=(%d,%d)\n", + pi->proto->name, pi->port, pi->mode, e[0], e[1]); + + return e[0] && e[1]; /* not here if both > 0 */ +} + +static int pi_test_proto(struct pi_adapter *pi, char *scratch) +{ + int res; + + parport_claim_or_block(pi->pardev); + if (pi->proto->test_proto) + res = pi->proto->test_proto(pi, scratch, 1); + else + res = default_test_proto(pi, scratch); + parport_release(pi->pardev); + + return res; +} + +static bool pi_probe_mode(struct pi_adapter *pi, int max, char *scratch) +{ + int best, range; + + if (pi->mode != -1) { + if (pi->mode >= max) + return false; + range = 3; + if (pi->mode >= pi->proto->epp_first) + range = 8; + if (range == 8 && pi->port % 8) + return false; + return !pi_test_proto(pi, scratch); + } + best = -1; + for (pi->mode = 0; pi->mode < max; pi->mode++) { + range = 3; + if (pi->mode >= pi->proto->epp_first) + range = 8; + if (range == 8 && pi->port % 8) + break; + if (!pi_test_proto(pi, scratch)) + best = pi->mode; + } + pi->mode = best; + return best > -1; +} + +static bool pi_probe_unit(struct pi_adapter *pi, int unit, char *scratch) +{ + int max, s, e; + + s = unit; + e = s + 1; + + if (s == -1) { + s = 0; + e = pi->proto->max_units; + } + + if (pi->proto->test_port) { + parport_claim_or_block(pi->pardev); + max = pi->proto->test_port(pi); + parport_release(pi->pardev); + } else { + max = pi->proto->max_mode; + } + + if (pi->proto->probe_unit) { + parport_claim_or_block(pi->pardev); + for (pi->unit = s; pi->unit < e; pi->unit++) { + if (pi->proto->probe_unit(pi)) { + parport_release(pi->pardev); + return pi_probe_mode(pi, max, scratch); + } + } + parport_release(pi->pardev); + return false; + } + + return pi_probe_mode(pi, max, scratch); +} + +static void pata_parport_dev_release(struct device *dev) +{ + struct pi_adapter *pi = container_of(dev, struct pi_adapter, dev); + + kfree(pi); +} + +static void pata_parport_bus_release(struct device *dev) +{ + /* nothing to do here but required to avoid warning on device removal */ +} + +static struct bus_type pata_parport_bus_type = { + .name = DRV_NAME, +}; + +static struct device pata_parport_bus = { + .init_name = DRV_NAME, + .release = pata_parport_bus_release, +}; + +static struct scsi_host_template pata_parport_sht = { + PATA_PARPORT_SHT("pata_parport") +}; + +struct pi_device_match { + struct parport *parport; + struct pi_protocol *proto; +}; + +static int pi_find_dev(struct device *dev, void *data) +{ + struct pi_adapter *pi = container_of(dev, struct pi_adapter, dev); + struct pi_device_match *match = data; + + return pi->pardev->port == match->parport && pi->proto == match->proto; +} + +static struct pi_adapter *pi_init_one(struct parport *parport, + struct pi_protocol *pr, int mode, int unit, int delay) +{ + struct pardev_cb par_cb = { }; + char scratch[512]; + const struct ata_port_info *ppi[] = { &pata_parport_port_info }; + struct ata_host *host; + struct pi_adapter *pi; + struct pi_device_match match = { .parport = parport, .proto = pr }; + int id; + + /* + * Abort if there's a device already registered on the same parport + * using the same protocol. + */ + if (bus_for_each_dev(&pata_parport_bus_type, NULL, &match, pi_find_dev)) + return NULL; + + pi = kzalloc(sizeof(struct pi_adapter), GFP_KERNEL); + if (!pi) + return NULL; + + /* set up pi->dev before pi_probe_unit() so it can use dev_printk() */ + pi->dev.parent = &pata_parport_bus; + pi->dev.bus = &pata_parport_bus_type; + pi->dev.driver = &pr->driver; + pi->dev.release = pata_parport_dev_release; + id = ida_alloc(&pata_parport_bus_dev_ids, GFP_KERNEL); + if (id < 0) + return NULL; /* pata_parport_dev_release will do kfree(pi) */ + pi->dev.id = id; + dev_set_name(&pi->dev, "pata_parport.%u", pi->dev.id); + if (device_register(&pi->dev)) { + put_device(&pi->dev); + goto out_ida_free; + } + + pi->proto = pr; + + if (!try_module_get(pi->proto->owner)) + goto out_unreg_dev; + if (pi->proto->init_proto && pi->proto->init_proto(pi) < 0) + goto out_module_put; + + pi->delay = (delay == -1) ? pi->proto->default_delay : delay; + pi->mode = mode; + pi->port = parport->base; + + par_cb.private = pi; + pi->pardev = parport_register_dev_model(parport, DRV_NAME, &par_cb, + pi->dev.id); + if (!pi->pardev) + goto out_module_put; + + if (!pi_probe_unit(pi, unit, scratch)) { + dev_info(&pi->dev, "Adapter not found\n"); + goto out_unreg_parport; + } + + pi->proto->log_adapter(pi, scratch, 1); + + host = ata_host_alloc_pinfo(&pi->pardev->dev, ppi, 1); + if (!host) + goto out_unreg_parport; + dev_set_drvdata(&pi->dev, host); + host->private_data = pi; + + ata_port_desc(host->ports[0], "port %s", pi->pardev->port->name); + ata_port_desc(host->ports[0], "protocol %s", pi->proto->name); + + pi_connect(pi); + if (ata_host_activate(host, 0, NULL, 0, &pata_parport_sht)) + goto out_unreg_parport; + + return pi; + +out_unreg_parport: + pi_disconnect(pi); + parport_unregister_device(pi->pardev); + if (pi->proto->release_proto) + pi->proto->release_proto(pi); +out_module_put: + module_put(pi->proto->owner); +out_unreg_dev: + device_unregister(&pi->dev); +out_ida_free: + ida_free(&pata_parport_bus_dev_ids, pi->dev.id); + return NULL; +} + +int pata_parport_register_driver(struct pi_protocol *pr) +{ + int error; + struct parport *parport; + int port_num; + + pr->driver.bus = &pata_parport_bus_type; + pr->driver.name = pr->name; + error = driver_register(&pr->driver); + if (error) + return error; + + mutex_lock(&pi_mutex); + error = idr_alloc(&protocols, pr, 0, 0, GFP_KERNEL); + if (error < 0) { + driver_unregister(&pr->driver); + mutex_unlock(&pi_mutex); + return error; + } + + pr_info("pata_parport: protocol %s registered\n", pr->name); + + if (probe) { + /* probe all parports using this protocol */ + idr_for_each_entry(&parport_list, parport, port_num) + pi_init_one(parport, pr, -1, 0, -1); + } + mutex_unlock(&pi_mutex); + + return 0; +} +EXPORT_SYMBOL_GPL(pata_parport_register_driver); + +void pata_parport_unregister_driver(struct pi_protocol *pr) +{ + struct pi_protocol *pr_iter; + int id = -1; + + mutex_lock(&pi_mutex); + idr_for_each_entry(&protocols, pr_iter, id) { + if (pr_iter == pr) + break; + } + idr_remove(&protocols, id); + mutex_unlock(&pi_mutex); + driver_unregister(&pr->driver); +} +EXPORT_SYMBOL_GPL(pata_parport_unregister_driver); + +static ssize_t new_device_store(struct bus_type *bus, const char *buf, + size_t count) +{ + char port[12] = "auto"; + char protocol[8] = "auto"; + int mode = -1, unit = -1, delay = -1; + struct pi_protocol *pr, *pr_wanted; + struct device_driver *drv; + struct parport *parport; + int port_num, port_wanted, pr_num; + bool ok = false; + + if (sscanf(buf, "%11s %7s %d %d %d", + port, protocol, &mode, &unit, &delay) < 1) + return -EINVAL; + + if (sscanf(port, "parport%u", &port_wanted) < 1) { + if (strcmp(port, "auto")) { + pr_err("invalid port name %s\n", port); + return -EINVAL; + } + port_wanted = -1; + } + + drv = driver_find(protocol, &pata_parport_bus_type); + if (!drv) { + if (strcmp(protocol, "auto")) { + pr_err("protocol %s not found\n", protocol); + return -EINVAL; + } + pr_wanted = NULL; + } else { + pr_wanted = container_of(drv, struct pi_protocol, driver); + } + + mutex_lock(&pi_mutex); + /* walk all parports */ + idr_for_each_entry(&parport_list, parport, port_num) { + if (port_num == port_wanted || port_wanted == -1) { + parport = parport_find_number(port_num); + if (!parport) { + pr_err("no such port %s\n", port); + mutex_unlock(&pi_mutex); + return -ENODEV; + } + /* walk all protocols */ + idr_for_each_entry(&protocols, pr, pr_num) { + if (pr == pr_wanted || !pr_wanted) + if (pi_init_one(parport, pr, mode, unit, + delay)) + ok = true; + } + parport_put_port(parport); + } + } + mutex_unlock(&pi_mutex); + if (!ok) + return -ENODEV; + + return count; +} +static BUS_ATTR_WO(new_device); + +static void pi_remove_one(struct device *dev) +{ + struct ata_host *host = dev_get_drvdata(dev); + struct pi_adapter *pi = host->private_data; + + ata_host_detach(host); + pi_disconnect(pi); + pi_release(pi); + device_unregister(dev); + ida_free(&pata_parport_bus_dev_ids, dev->id); + /* pata_parport_dev_release will do kfree(pi) */ +} + +static ssize_t delete_device_store(struct bus_type *bus, const char *buf, + size_t count) +{ + struct device *dev; + + mutex_lock(&pi_mutex); + dev = bus_find_device_by_name(bus, NULL, buf); + if (!dev) { + mutex_unlock(&pi_mutex); + return -ENODEV; + } + + pi_remove_one(dev); + mutex_unlock(&pi_mutex); + + return count; +} +static BUS_ATTR_WO(delete_device); + +static void pata_parport_attach(struct parport *port) +{ + struct pi_protocol *pr; + int pr_num, id; + + mutex_lock(&pi_mutex); + id = idr_alloc(&parport_list, port, port->number, port->number, + GFP_KERNEL); + if (id < 0) { + mutex_unlock(&pi_mutex); + return; + } + + if (probe) { + /* probe this port using all protocols */ + idr_for_each_entry(&protocols, pr, pr_num) + pi_init_one(port, pr, -1, 0, -1); + } + mutex_unlock(&pi_mutex); +} + +static int pi_remove_port(struct device *dev, void *p) +{ + struct ata_host *host = dev_get_drvdata(dev); + struct pi_adapter *pi = host->private_data; + + if (pi->pardev->port == p) + pi_remove_one(dev); + + return 0; +} + +static void pata_parport_detach(struct parport *port) +{ + mutex_lock(&pi_mutex); + bus_for_each_dev(&pata_parport_bus_type, NULL, port, pi_remove_port); + idr_remove(&parport_list, port->number); + mutex_unlock(&pi_mutex); +} + +static struct parport_driver pata_parport_driver = { + .name = DRV_NAME, + .match_port = pata_parport_attach, + .detach = pata_parport_detach, + .devmodel = true, +}; + +static __init int pata_parport_init(void) +{ + int error; + + error = bus_register(&pata_parport_bus_type); + if (error) { + pr_err("failed to register pata_parport bus, error: %d\n", error); + return error; + } + + error = device_register(&pata_parport_bus); + if (error) { + pr_err("failed to register pata_parport bus, error: %d\n", error); + goto out_unregister_bus; + } + + error = bus_create_file(&pata_parport_bus_type, &bus_attr_new_device); + if (error) { + pr_err("unable to create sysfs file, error: %d\n", error); + goto out_unregister_dev; + } + + error = bus_create_file(&pata_parport_bus_type, &bus_attr_delete_device); + if (error) { + pr_err("unable to create sysfs file, error: %d\n", error); + goto out_remove_new; + } + + error = parport_register_driver(&pata_parport_driver); + if (error) { + pr_err("unable to register parport driver, error: %d\n", error); + goto out_remove_del; + } + + return 0; + +out_remove_del: + bus_remove_file(&pata_parport_bus_type, &bus_attr_delete_device); +out_remove_new: + bus_remove_file(&pata_parport_bus_type, &bus_attr_new_device); +out_unregister_dev: + device_unregister(&pata_parport_bus); +out_unregister_bus: + bus_unregister(&pata_parport_bus_type); + return error; +} + +static __exit void pata_parport_exit(void) +{ + parport_unregister_driver(&pata_parport_driver); + bus_remove_file(&pata_parport_bus_type, &bus_attr_new_device); + bus_remove_file(&pata_parport_bus_type, &bus_attr_delete_device); + device_unregister(&pata_parport_bus); + bus_unregister(&pata_parport_bus_type); +} + +MODULE_AUTHOR("Ondrej Zary"); +MODULE_DESCRIPTION("driver for parallel port ATA adapters"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("paride"); + +module_init(pata_parport_init); +module_exit(pata_parport_exit); diff --git a/drivers/block/paride/ppc6lnx.c b/drivers/ata/pata_parport/ppc6lnx.c index 5e5521d3b1dd..5e5521d3b1dd 100644 --- a/drivers/block/paride/ppc6lnx.c +++ b/drivers/ata/pata_parport/ppc6lnx.c diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index b9a4f68b371d..b052c5a65c17 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -566,7 +566,7 @@ static unsigned int sata_fsl_qc_issue(struct ata_queued_cmd *qc) return 0; } -static bool sata_fsl_qc_fill_rtf(struct ata_queued_cmd *qc) +static void sata_fsl_qc_fill_rtf(struct ata_queued_cmd *qc) { struct sata_fsl_port_priv *pp = qc->ap->private_data; struct sata_fsl_host_priv *host_priv = qc->ap->host->private_data; @@ -577,7 +577,6 @@ static bool sata_fsl_qc_fill_rtf(struct ata_queued_cmd *qc) cd = pp->cmdentry + tag; ata_tf_from_fis(cd->sfis, &qc->result_tf); - return true; } static int sata_fsl_scr_write(struct ata_link *link, @@ -1042,7 +1041,7 @@ static void sata_fsl_error_handler(struct ata_port *ap) static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc) { - if (qc->flags & ATA_QCFLAG_FAILED) + if (qc->flags & ATA_QCFLAG_EH) qc->err_mask |= AC_ERR_OTHER; if (qc->err_mask) { diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 11e518f0111c..2833c722118d 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -566,7 +566,7 @@ static void inic_tf_read(struct ata_port *ap, struct ata_taskfile *tf) tf->status = readb(port_base + PORT_TF_COMMAND); } -static bool inic_qc_fill_rtf(struct ata_queued_cmd *qc) +static void inic_qc_fill_rtf(struct ata_queued_cmd *qc) { struct ata_taskfile *rtf = &qc->result_tf; struct ata_taskfile tf; @@ -580,12 +580,10 @@ static bool inic_qc_fill_rtf(struct ata_queued_cmd *qc) */ inic_tf_read(qc->ap, &tf); - if (!(tf.status & ATA_ERR)) - return false; - - rtf->status = tf.status; - rtf->error = tf.error; - return true; + if (tf.status & ATA_ERR) { + rtf->status = tf.status; + rtf->error = tf.error; + } } static void inic_freeze(struct ata_port *ap) @@ -672,7 +670,7 @@ static void inic_error_handler(struct ata_port *ap) static void inic_post_internal_cmd(struct ata_queued_cmd *qc) { /* make DMA engine forget about the failed command */ - if (qc->flags & ATA_QCFLAG_FAILED) + if (qc->flags & ATA_QCFLAG_EH) inic_reset_port(inic_port_base(qc->ap)); } diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 9cd7d8b71361..4e60e6c4c35a 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -828,7 +828,7 @@ static void pdc_post_internal_cmd(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; /* make DMA engine forget about the failed command */ - if (qc->flags & ATA_QCFLAG_FAILED) + if (qc->flags & ATA_QCFLAG_EH) pdc_reset_port(ap); } diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 2fef6ce93f07..22cc9e9789dd 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -328,7 +328,7 @@ static int sil24_scr_write(struct ata_link *link, unsigned sc_reg, u32 val); static int sil24_qc_defer(struct ata_queued_cmd *qc); static enum ata_completion_errors sil24_qc_prep(struct ata_queued_cmd *qc); static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc); -static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc); +static void sil24_qc_fill_rtf(struct ata_queued_cmd *qc); static void sil24_pmp_attach(struct ata_port *ap); static void sil24_pmp_detach(struct ata_port *ap); static void sil24_freeze(struct ata_port *ap); @@ -901,10 +901,9 @@ static unsigned int sil24_qc_issue(struct ata_queued_cmd *qc) return 0; } -static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc) +static void sil24_qc_fill_rtf(struct ata_queued_cmd *qc) { sil24_read_tf(qc->ap, qc->hw_tag, &qc->result_tf); - return true; } static void sil24_pmp_attach(struct ata_port *ap) @@ -1185,7 +1184,7 @@ static void sil24_post_internal_cmd(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; /* make DMA engine forget about the failed command */ - if ((qc->flags & ATA_QCFLAG_FAILED) && sil24_init_port(ap)) + if ((qc->flags & ATA_QCFLAG_EH) && sil24_init_port(ap)) ata_eh_freeze_port(ap); } diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index ab70cbc78f96..a92c60455b1d 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -866,7 +866,7 @@ static void pdc_post_internal_cmd(struct ata_queued_cmd *qc) struct ata_port *ap = qc->ap; /* make DMA engine forget about the failed command */ - if (qc->flags & ATA_QCFLAG_FAILED) + if (qc->flags & ATA_QCFLAG_EH) pdc_reset_port(ap); } diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index a41145d52de9..f79f20430ef7 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -103,35 +103,6 @@ config GDROM Most users will want to say "Y" here. You can also build this as a module which will be called gdrom. -config PARIDE - tristate "Parallel port IDE device support" - depends on PARPORT_PC - help - There are many external CD-ROM and disk devices that connect through - your computer's parallel port. Most of them are actually IDE devices - using a parallel port IDE adapter. This option enables the PARIDE - subsystem which contains drivers for many of these external drives. - Read <file:Documentation/admin-guide/blockdev/paride.rst> for more information. - - If you have said Y to the "Parallel-port support" configuration - option, you may share a single port between your printer and other - parallel port devices. Answer Y to build PARIDE support into your - kernel, or M if you would like to build it as a loadable module. If - your parallel port support is in a loadable module, you must build - PARIDE as a module. If you built PARIDE support into your kernel, - you may still build the individual protocol modules and high-level - drivers as loadable modules. If you build this support as a module, - it will be called paride. - - To use the PARIDE support, you must say Y or M here and also to at - least one high-level driver (e.g. "Parallel port IDE disks", - "Parallel port ATAPI CD-ROMs", "Parallel port ATAPI disks" etc.) and - to at least one protocol driver (e.g. "ATEN EH-100 protocol", - "MicroSolutions backpack protocol", "DataStor Commuter protocol" - etc.). - -source "drivers/block/paride/Kconfig" - source "drivers/block/mtip32xx/Kconfig" source "drivers/block/zram/Kconfig" diff --git a/drivers/block/paride/Kconfig b/drivers/block/paride/Kconfig deleted file mode 100644 index a295634597ba..000000000000 --- a/drivers/block/paride/Kconfig +++ /dev/null @@ -1,302 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# PARIDE configuration -# -# PARIDE doesn't need PARPORT, but if PARPORT is configured as a module, -# PARIDE must also be a module. -# PARIDE only supports PC style parports. Tough for USB or other parports... - -comment "Parallel IDE high-level drivers" - depends on PARIDE - -config PARIDE_PD - tristate "Parallel port IDE disks" - depends on PARIDE - help - This option enables the high-level driver for IDE-type disk devices - connected through a parallel port. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - parallel port IDE driver, otherwise you should answer M to build - it as a loadable module. The module will be called pd. You - must also have at least one parallel port protocol driver in your - system. Among the devices supported by this driver are the SyQuest - EZ-135, EZ-230 and SparQ drives, the Avatar Shark and the backpack - hard drives from MicroSolutions. - -config PARIDE_PCD - tristate "Parallel port ATAPI CD-ROMs" - depends on PARIDE - select CDROM - help - This option enables the high-level driver for ATAPI CD-ROM devices - connected through a parallel port. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - parallel port ATAPI CD-ROM driver, otherwise you should answer M to - build it as a loadable module. The module will be called pcd. You - must also have at least one parallel port protocol driver in your - system. Among the devices supported by this driver are the - MicroSolutions backpack CD-ROM drives and the Freecom Power CD. If - you have such a CD-ROM drive, you should also say Y or M to "ISO - 9660 CD-ROM file system support" below, because that's the file - system used on CD-ROMs. - -config PARIDE_PF - tristate "Parallel port ATAPI disks" - depends on PARIDE - help - This option enables the high-level driver for ATAPI disk devices - connected through a parallel port. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - parallel port ATAPI disk driver, otherwise you should answer M - to build it as a loadable module. The module will be called pf. - You must also have at least one parallel port protocol driver in - your system. Among the devices supported by this driver are the - MicroSolutions backpack PD/CD drive and the Imation Superdisk - LS-120 drive. - -config PARIDE_PT - tristate "Parallel port ATAPI tapes" - depends on PARIDE - help - This option enables the high-level driver for ATAPI tape devices - connected through a parallel port. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - parallel port ATAPI disk driver, otherwise you should answer M - to build it as a loadable module. The module will be called pt. - You must also have at least one parallel port protocol driver in - your system. Among the devices supported by this driver is the - parallel port version of the HP 5GB drive. - -config PARIDE_PG - tristate "Parallel port generic ATAPI devices" - depends on PARIDE - help - This option enables a special high-level driver for generic ATAPI - devices connected through a parallel port. The driver allows user - programs, such as cdrtools, to send ATAPI commands directly to a - device. - - If you chose to build PARIDE support into your kernel, you may - answer Y here to build in the parallel port generic ATAPI driver, - otherwise you should answer M to build it as a loadable module. The - module will be called pg. - - You must also have at least one parallel port protocol driver in - your system. - - This driver implements an API loosely related to the generic SCSI - driver. See <file:include/linux/pg.h>. for details. - - You can obtain the most recent version of cdrtools from - <ftp://ftp.berlios.de/pub/cdrecord/>. Versions 1.6.1a3 and - later fully support this driver. - -comment "Parallel IDE protocol modules" - depends on PARIDE - -config PARIDE_ATEN - tristate "ATEN EH-100 protocol" - depends on PARIDE - help - This option enables support for the ATEN EH-100 parallel port IDE - protocol. This protocol is used in some inexpensive low performance - parallel port kits made in Hong Kong. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - protocol driver, otherwise you should answer M to build it as a - loadable module. The module will be called aten. You must also - have a high-level driver for the type of device that you want to - support. - -config PARIDE_BPCK - tristate "MicroSolutions backpack (Series 5) protocol" - depends on PARIDE - help - This option enables support for the Micro Solutions BACKPACK - parallel port Series 5 IDE protocol. (Most BACKPACK drives made - before 1999 were Series 5) Series 5 drives will NOT always have the - Series noted on the bottom of the drive. Series 6 drivers will. - - In other words, if your BACKPACK drive doesn't say "Series 6" on the - bottom, enable this option. - - If you chose to build PARIDE support into your kernel, you may - answer Y here to build in the protocol driver, otherwise you should - answer M to build it as a loadable module. The module will be - called bpck. You must also have a high-level driver for the type - of device that you want to support. - -config PARIDE_BPCK6 - tristate "MicroSolutions backpack (Series 6) protocol" - depends on PARIDE && !64BIT - help - This option enables support for the Micro Solutions BACKPACK - parallel port Series 6 IDE protocol. (Most BACKPACK drives made - after 1999 were Series 6) Series 6 drives will have the Series noted - on the bottom of the drive. Series 5 drivers don't always have it - noted. - - In other words, if your BACKPACK drive says "Series 6" on the - bottom, enable this option. - - If you chose to build PARIDE support into your kernel, you may - answer Y here to build in the protocol driver, otherwise you should - answer M to build it as a loadable module. The module will be - called bpck6. You must also have a high-level driver for the type - of device that you want to support. - -config PARIDE_COMM - tristate "DataStor Commuter protocol" - depends on PARIDE - help - This option enables support for the Commuter parallel port IDE - protocol from DataStor. If you chose to build PARIDE support - into your kernel, you may answer Y here to build in the protocol - driver, otherwise you should answer M to build it as a loadable - module. The module will be called comm. You must also have - a high-level driver for the type of device that you want to support. - -config PARIDE_DSTR - tristate "DataStor EP-2000 protocol" - depends on PARIDE - help - This option enables support for the EP-2000 parallel port IDE - protocol from DataStor. If you chose to build PARIDE support - into your kernel, you may answer Y here to build in the protocol - driver, otherwise you should answer M to build it as a loadable - module. The module will be called dstr. You must also have - a high-level driver for the type of device that you want to support. - -config PARIDE_FIT2 - tristate "FIT TD-2000 protocol" - depends on PARIDE - help - This option enables support for the TD-2000 parallel port IDE - protocol from Fidelity International Technology. This is a simple - (low speed) adapter that is used in some portable hard drives. If - you chose to build PARIDE support into your kernel, you may answer Y - here to build in the protocol driver, otherwise you should answer M - to build it as a loadable module. The module will be called ktti. - You must also have a high-level driver for the type of device that - you want to support. - -config PARIDE_FIT3 - tristate "FIT TD-3000 protocol" - depends on PARIDE - help - This option enables support for the TD-3000 parallel port IDE - protocol from Fidelity International Technology. This protocol is - used in newer models of their portable disk, CD-ROM and PD/CD - devices. If you chose to build PARIDE support into your kernel, you - may answer Y here to build in the protocol driver, otherwise you - should answer M to build it as a loadable module. The module will be - called fit3. You must also have a high-level driver for the type - of device that you want to support. - -config PARIDE_EPAT - tristate "Shuttle EPAT/EPEZ protocol" - depends on PARIDE - help - This option enables support for the EPAT parallel port IDE protocol. - EPAT is a parallel port IDE adapter manufactured by Shuttle - Technology and widely used in devices from major vendors such as - Hewlett-Packard, SyQuest, Imation and Avatar. If you chose to build - PARIDE support into your kernel, you may answer Y here to build in - the protocol driver, otherwise you should answer M to build it as a - loadable module. The module will be called epat. You must also - have a high-level driver for the type of device that you want to - support. - -config PARIDE_EPATC8 - bool "Support c7/c8 chips" - depends on PARIDE_EPAT - help - This option enables support for the newer Shuttle EP1284 (aka c7 and - c8) chip. You need this if you are using any recent Imation SuperDisk - (LS-120) drive. - -config PARIDE_EPIA - tristate "Shuttle EPIA protocol" - depends on PARIDE - help - This option enables support for the (obsolete) EPIA parallel port - IDE protocol from Shuttle Technology. This adapter can still be - found in some no-name kits. If you chose to build PARIDE support - into your kernel, you may answer Y here to build in the protocol - driver, otherwise you should answer M to build it as a loadable - module. The module will be called epia. You must also have a - high-level driver for the type of device that you want to support. - -config PARIDE_FRIQ - tristate "Freecom IQ ASIC-2 protocol" - depends on PARIDE - help - This option enables support for version 2 of the Freecom IQ parallel - port IDE adapter. This adapter is used by the Maxell Superdisk - drive. If you chose to build PARIDE support into your kernel, you - may answer Y here to build in the protocol driver, otherwise you - should answer M to build it as a loadable module. The module will be - called friq. You must also have a high-level driver for the type - of device that you want to support. - -config PARIDE_FRPW - tristate "FreeCom power protocol" - depends on PARIDE - help - This option enables support for the Freecom power parallel port IDE - protocol. If you chose to build PARIDE support into your kernel, you - may answer Y here to build in the protocol driver, otherwise you - should answer M to build it as a loadable module. The module will be - called frpw. You must also have a high-level driver for the type - of device that you want to support. - -config PARIDE_KBIC - tristate "KingByte KBIC-951A/971A protocols" - depends on PARIDE - help - This option enables support for the KBIC-951A and KBIC-971A parallel - port IDE protocols from KingByte Information Corp. KingByte's - adapters appear in many no-name portable disk and CD-ROM products, - especially in Europe. If you chose to build PARIDE support into your - kernel, you may answer Y here to build in the protocol driver, - otherwise you should answer M to build it as a loadable module. The - module will be called kbic. You must also have a high-level driver - for the type of device that you want to support. - -config PARIDE_KTTI - tristate "KT PHd protocol" - depends on PARIDE - help - This option enables support for the "PHd" parallel port IDE protocol - from KT Technology. This is a simple (low speed) adapter that is - used in some 2.5" portable hard drives. If you chose to build PARIDE - support into your kernel, you may answer Y here to build in the - protocol driver, otherwise you should answer M to build it as a - loadable module. The module will be called ktti. You must also - have a high-level driver for the type of device that you want to - support. - -config PARIDE_ON20 - tristate "OnSpec 90c20 protocol" - depends on PARIDE - help - This option enables support for the (obsolete) 90c20 parallel port - IDE protocol from OnSpec (often marketed under the ValuStore brand - name). If you chose to build PARIDE support into your kernel, you - may answer Y here to build in the protocol driver, otherwise you - should answer M to build it as a loadable module. The module will - be called on20. You must also have a high-level driver for the - type of device that you want to support. - -config PARIDE_ON26 - tristate "OnSpec 90c26 protocol" - depends on PARIDE - help - This option enables support for the 90c26 parallel port IDE protocol - from OnSpec Electronics (often marketed under the ValuStore brand - name). If you chose to build PARIDE support into your kernel, you - may answer Y here to build in the protocol driver, otherwise you - should answer M to build it as a loadable module. The module will be - called on26. You must also have a high-level driver for the type - of device that you want to support. - -# diff --git a/drivers/block/paride/Makefile b/drivers/block/paride/Makefile deleted file mode 100644 index cf1742a8475e..000000000000 --- a/drivers/block/paride/Makefile +++ /dev/null @@ -1,29 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for Parallel port IDE device drivers. -# -# 7 October 2000, Bartlomiej Zolnierkiewicz <bkz@linux-ide.org> -# Rewritten to use lists instead of if-statements. -# - -obj-$(CONFIG_PARIDE) += paride.o -obj-$(CONFIG_PARIDE_ATEN) += aten.o -obj-$(CONFIG_PARIDE_BPCK) += bpck.o -obj-$(CONFIG_PARIDE_COMM) += comm.o -obj-$(CONFIG_PARIDE_DSTR) += dstr.o -obj-$(CONFIG_PARIDE_KBIC) += kbic.o -obj-$(CONFIG_PARIDE_EPAT) += epat.o -obj-$(CONFIG_PARIDE_EPIA) += epia.o -obj-$(CONFIG_PARIDE_FRPW) += frpw.o -obj-$(CONFIG_PARIDE_FRIQ) += friq.o -obj-$(CONFIG_PARIDE_FIT2) += fit2.o -obj-$(CONFIG_PARIDE_FIT3) += fit3.o -obj-$(CONFIG_PARIDE_ON20) += on20.o -obj-$(CONFIG_PARIDE_ON26) += on26.o -obj-$(CONFIG_PARIDE_KTTI) += ktti.o -obj-$(CONFIG_PARIDE_BPCK6) += bpck6.o -obj-$(CONFIG_PARIDE_PD) += pd.o -obj-$(CONFIG_PARIDE_PCD) += pcd.o -obj-$(CONFIG_PARIDE_PF) += pf.o -obj-$(CONFIG_PARIDE_PT) += pt.o -obj-$(CONFIG_PARIDE_PG) += pg.o diff --git a/drivers/block/paride/Transition-notes b/drivers/block/paride/Transition-notes deleted file mode 100644 index 70374907c020..000000000000 --- a/drivers/block/paride/Transition-notes +++ /dev/null @@ -1,128 +0,0 @@ -Lemma 1: - If ps_tq is scheduled, ps_tq_active is 1. ps_tq_int() can be called - only when ps_tq_active is 1. -Proof: All assignments to ps_tq_active and all scheduling of ps_tq happen - under ps_spinlock. There are three places where that can happen: - one in ps_set_intr() (A) and two in ps_tq_int() (B and C). - Consider the sequnce of these events. A can not be preceded by - anything except B, since it is under if (!ps_tq_active) under - ps_spinlock. C is always preceded by B, since we can't reach it - other than through B and we don't drop ps_spinlock between them. - IOW, the sequence is A?(BA|BC|B)*. OTOH, number of B can not exceed - the sum of numbers of A and C, since each call of ps_tq_int() is - the result of ps_tq execution. Therefore, the sequence starts with - A and each B is preceded by either A or C. Moments when we enter - ps_tq_int() are sandwiched between {A,C} and B in that sequence, - since at any time number of B can not exceed the number of these - moments which, in turn, can not exceed the number of A and C. - In other words, the sequence of events is (A or C set ps_tq_active to - 1 and schedule ps_tq, ps_tq is executed, ps_tq_int() is entered, - B resets ps_tq_active)*. - - -consider the following area: - * in do_pd_request1(): to calls of pi_do_claimed() and return in - case when pd_req is NULL. - * in next_request(): to call of do_pd_request1() - * in do_pd_read(): to call of ps_set_intr() - * in do_pd_read_start(): to calls of pi_do_claimed(), next_request() -and ps_set_intr() - * in do_pd_read_drq(): to calls of pi_do_claimed() and next_request() - * in do_pd_write(): to call of ps_set_intr() - * in do_pd_write_start(): to calls of pi_do_claimed(), next_request() -and ps_set_intr() - * in do_pd_write_done(): to calls of pi_do_claimed() and next_request() - * in ps_set_intr(): to check for ps_tq_active and to scheduling - ps_tq if ps_tq_active was 0. - * in ps_tq_int(): from the moment when we get ps_spinlock() to the - return, call of con() or scheduling ps_tq. - * in pi_schedule_claimed() when called from pi_do_claimed() called from - pd.c, everything until returning 1 or setting or setting ->claim_cont - on the path that returns 0 - * in pi_do_claimed() when called from pd.c, everything until the call - of pi_do_claimed() plus the everything until the call of cont() if - pi_do_claimed() has returned 1. - * in pi_wake_up() called for PIA that belongs to pd.c, everything from - the moment when pi_spinlock has been acquired. - -Lemma 2: - 1) at any time at most one thread of execution can be in that area or - be preempted there. - 2) When there is such a thread, pd_busy is set or pd_lock is held by - that thread. - 3) When there is such a thread, ps_tq_active is 0 or ps_spinlock is - held by that thread. - 4) When there is such a thread, all PIA belonging to pd.c have NULL - ->claim_cont or pi_spinlock is held by thread in question. - -Proof: consider the first moment when the above is not true. - -(1) can become not true if some thread enters that area while another is there. - a) do_pd_request1() can be called from next_request() or do_pd_request() - In the first case the thread was already in the area. In the second, - the thread was holding pd_lock and found pd_busy not set, which would - mean that (2) was already not true. - b) ps_set_intr() and pi_schedule_claimed() can be called only from the - area. - c) pi_do_claimed() is called by pd.c only from the area. - d) ps_tq_int() can enter the area only when the thread is holding - ps_spinlock and ps_tq_active is 1 (due to Lemma 1). It means that - (3) was already not true. - e) do_pd_{read,write}* could be called only from the area. The only - case that needs consideration is call from pi_wake_up() and there - we would have to be called for the PIA that got ->claimed_cont - from pd.c. That could happen only if pi_do_claimed() had been - called from pd.c for that PIA, which happens only for PIA belonging - to pd.c. - f) pi_wake_up() can enter the area only when the thread is holding - pi_spinlock and ->claimed_cont is non-NULL for PIA belonging to - pd.c. It means that (4) was already not true. - -(2) can become not true only when pd_lock is released by the thread in question. - Indeed, pd_busy is reset only in the area and thread that resets - it is holding pd_lock. The only place within the area where we - release pd_lock is in pd_next_buf() (called from within the area). - But that code does not reset pd_busy, so pd_busy would have to be - 0 when pd_next_buf() had acquired pd_lock. If it become 0 while - we were acquiring the lock, (1) would be already false, since - the thread that had reset it would be in the area simulateously. - If it was 0 before we tried to acquire pd_lock, (2) would be - already false. - -For similar reasons, (3) can become not true only when ps_spinlock is released -by the thread in question. However, all such places within the area are right -after resetting ps_tq_active to 0. - -(4) is done the same way - all places where we release pi_spinlock within -the area are either after resetting ->claimed_cont to NULL while holding -pi_spinlock, or after not tocuhing ->claimed_cont since acquiring pi_spinlock -also in the area. The only place where ->claimed_cont is made non-NULL is -in the area, under pi_spinlock and we do not release it until after leaving -the area. - -QED. - - -Corollary 1: ps_tq_active can be killed. Indeed, the only place where we -check its value is in ps_set_intr() and if it had been non-zero at that -point, we would have violated either (2.1) (if it was set while ps_set_intr() -was acquiring ps_spinlock) or (2.3) (if it was set when we started to -acquire ps_spinlock). - -Corollary 2: ps_spinlock can be killed. Indeed, Lemma 1 and Lemma 2 show -that the only possible contention is between scheduling ps_tq followed by -immediate release of spinlock and beginning of execution of ps_tq on -another CPU. - -Corollary 3: assignment to pd_busy in do_pd_read_start() and do_pd_write_start() -can be killed. Indeed, we are not holding pd_lock and thus pd_busy is already -1 here. - -Corollary 4: in ps_tq_int() uses of con can be replaced with uses of -ps_continuation, since the latter is changed only from the area. -We don't need to reset it to NULL, since we are guaranteed that there -will be a call of ps_set_intr() before we look at ps_continuation again. -We can remove the check for ps_continuation being NULL for the same -reason - the value is guaranteed to be set by the last ps_set_intr() and -we never pass it NULL. Assignements in the beginning of ps_set_intr() -can be taken to callers as long as they remain within the area. diff --git a/drivers/block/paride/mkd b/drivers/block/paride/mkd deleted file mode 100644 index 6d0d802479ea..000000000000 --- a/drivers/block/paride/mkd +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash -# SPDX-License-Identifier: GPL-2.0 -# -# mkd -- a script to create the device special files for the PARIDE subsystem -# -# block devices: pd (45), pcd (46), pf (47) -# character devices: pt (96), pg (97) -# -function mkdev { - mknod $1 $2 $3 $4 ; chmod 0660 $1 ; chown root:disk $1 -} -# -function pd { - D=$( printf \\$( printf "x%03x" $[ $1 + 97 ] ) ) - mkdev pd$D b 45 $[ $1 * 16 ] - for P in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - do mkdev pd$D$P b 45 $[ $1 * 16 + $P ] - done -} -# -cd /dev -# -for u in 0 1 2 3 ; do pd $u ; done -for u in 0 1 2 3 ; do mkdev pcd$u b 46 $u ; done -for u in 0 1 2 3 ; do mkdev pf$u b 47 $u ; done -for u in 0 1 2 3 ; do mkdev pt$u c 96 $u ; done -for u in 0 1 2 3 ; do mkdev npt$u c 96 $[ $u + 128 ] ; done -for u in 0 1 2 3 ; do mkdev pg$u c 97 $u ; done -# -# end of mkd - diff --git a/drivers/block/paride/paride.c b/drivers/block/paride/paride.c deleted file mode 100644 index 0e287993b778..000000000000 --- a/drivers/block/paride/paride.c +++ /dev/null @@ -1,479 +0,0 @@ -/* - paride.c (c) 1997-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - This is the base module for the family of device drivers - that support parallel port IDE devices. - -*/ - -/* Changes: - - 1.01 GRG 1998.05.03 Use spinlocks - 1.02 GRG 1998.05.05 init_proto, release_proto, ktti - 1.03 GRG 1998.08.15 eliminate compiler warning - 1.04 GRG 1998.11.28 added support for FRIQ - 1.05 TMW 2000.06.06 use parport_find_number instead of - parport_enumerate - 1.06 TMW 2001.03.26 more sane parport-or-not resource management -*/ - -#define PI_VERSION "1.06" - -#include <linux/module.h> -#include <linux/kmod.h> -#include <linux/types.h> -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/string.h> -#include <linux/spinlock.h> -#include <linux/wait.h> -#include <linux/sched.h> /* TASK_* */ -#include <linux/parport.h> -#include <linux/slab.h> - -#include "paride.h" - -MODULE_LICENSE("GPL"); - -#define MAX_PROTOS 32 - -static struct pi_protocol *protocols[MAX_PROTOS]; - -static DEFINE_SPINLOCK(pi_spinlock); - -void pi_write_regr(PIA * pi, int cont, int regr, int val) -{ - pi->proto->write_regr(pi, cont, regr, val); -} - -EXPORT_SYMBOL(pi_write_regr); - -int pi_read_regr(PIA * pi, int cont, int regr) -{ - return pi->proto->read_regr(pi, cont, regr); -} - -EXPORT_SYMBOL(pi_read_regr); - -void pi_write_block(PIA * pi, char *buf, int count) -{ - pi->proto->write_block(pi, buf, count); -} - -EXPORT_SYMBOL(pi_write_block); - -void pi_read_block(PIA * pi, char *buf, int count) -{ - pi->proto->read_block(pi, buf, count); -} - -EXPORT_SYMBOL(pi_read_block); - -static void pi_wake_up(void *p) -{ - PIA *pi = (PIA *) p; - unsigned long flags; - void (*cont) (void) = NULL; - - spin_lock_irqsave(&pi_spinlock, flags); - - if (pi->claim_cont && !parport_claim(pi->pardev)) { - cont = pi->claim_cont; - pi->claim_cont = NULL; - pi->claimed = 1; - } - - spin_unlock_irqrestore(&pi_spinlock, flags); - - wake_up(&(pi->parq)); - - if (cont) - cont(); -} - -int pi_schedule_claimed(PIA * pi, void (*cont) (void)) -{ - unsigned long flags; - - spin_lock_irqsave(&pi_spinlock, flags); - if (pi->pardev && parport_claim(pi->pardev)) { - pi->claim_cont = cont; - spin_unlock_irqrestore(&pi_spinlock, flags); - return 0; - } - pi->claimed = 1; - spin_unlock_irqrestore(&pi_spinlock, flags); - return 1; -} -EXPORT_SYMBOL(pi_schedule_claimed); - -void pi_do_claimed(PIA * pi, void (*cont) (void)) -{ - if (pi_schedule_claimed(pi, cont)) - cont(); -} - -EXPORT_SYMBOL(pi_do_claimed); - -static void pi_claim(PIA * pi) -{ - if (pi->claimed) - return; - pi->claimed = 1; - if (pi->pardev) - wait_event(pi->parq, - !parport_claim((struct pardevice *) pi->pardev)); -} - -static void pi_unclaim(PIA * pi) -{ - pi->claimed = 0; - if (pi->pardev) - parport_release((struct pardevice *) (pi->pardev)); -} - -void pi_connect(PIA * pi) -{ - pi_claim(pi); - pi->proto->connect(pi); -} - -EXPORT_SYMBOL(pi_connect); - -void pi_disconnect(PIA * pi) -{ - pi->proto->disconnect(pi); - pi_unclaim(pi); -} - -EXPORT_SYMBOL(pi_disconnect); - -static void pi_unregister_parport(PIA * pi) -{ - if (pi->pardev) { - parport_unregister_device((struct pardevice *) (pi->pardev)); - pi->pardev = NULL; - } -} - -void pi_release(PIA * pi) -{ - pi_unregister_parport(pi); - if (pi->proto->release_proto) - pi->proto->release_proto(pi); - module_put(pi->proto->owner); -} - -EXPORT_SYMBOL(pi_release); - -static int default_test_proto(PIA * pi, char *scratch, int verbose) -{ - int j, k; - int e[2] = { 0, 0 }; - - pi->proto->connect(pi); - - for (j = 0; j < 2; j++) { - pi_write_regr(pi, 0, 6, 0xa0 + j * 0x10); - for (k = 0; k < 256; k++) { - pi_write_regr(pi, 0, 2, k ^ 0xaa); - pi_write_regr(pi, 0, 3, k ^ 0x55); - if (pi_read_regr(pi, 0, 2) != (k ^ 0xaa)) - e[j]++; - } - } - pi->proto->disconnect(pi); - - if (verbose) - printk("%s: %s: port 0x%x, mode %d, test=(%d,%d)\n", - pi->device, pi->proto->name, pi->port, - pi->mode, e[0], e[1]); - - return (e[0] && e[1]); /* not here if both > 0 */ -} - -static int pi_test_proto(PIA * pi, char *scratch, int verbose) -{ - int res; - - pi_claim(pi); - if (pi->proto->test_proto) - res = pi->proto->test_proto(pi, scratch, verbose); - else - res = default_test_proto(pi, scratch, verbose); - pi_unclaim(pi); - - return res; -} - -int paride_register(PIP * pr) -{ - int k; - - for (k = 0; k < MAX_PROTOS; k++) - if (protocols[k] && !strcmp(pr->name, protocols[k]->name)) { - printk("paride: %s protocol already registered\n", - pr->name); - return -1; - } - k = 0; - while ((k < MAX_PROTOS) && (protocols[k])) - k++; - if (k == MAX_PROTOS) { - printk("paride: protocol table full\n"); - return -1; - } - protocols[k] = pr; - pr->index = k; - printk("paride: %s registered as protocol %d\n", pr->name, k); - return 0; -} - -EXPORT_SYMBOL(paride_register); - -void paride_unregister(PIP * pr) -{ - if (!pr) - return; - if (protocols[pr->index] != pr) { - printk("paride: %s not registered\n", pr->name); - return; - } - protocols[pr->index] = NULL; -} - -EXPORT_SYMBOL(paride_unregister); - -static int pi_register_parport(PIA *pi, int verbose, int unit) -{ - struct parport *port; - struct pardev_cb par_cb; - - port = parport_find_base(pi->port); - if (!port) - return 0; - memset(&par_cb, 0, sizeof(par_cb)); - par_cb.wakeup = pi_wake_up; - par_cb.private = (void *)pi; - pi->pardev = parport_register_dev_model(port, pi->device, &par_cb, - unit); - parport_put_port(port); - if (!pi->pardev) - return 0; - - init_waitqueue_head(&pi->parq); - - if (verbose) - printk("%s: 0x%x is %s\n", pi->device, pi->port, port->name); - - pi->parname = (char *) port->name; - - return 1; -} - -static int pi_probe_mode(PIA * pi, int max, char *scratch, int verbose) -{ - int best, range; - - if (pi->mode != -1) { - if (pi->mode >= max) - return 0; - range = 3; - if (pi->mode >= pi->proto->epp_first) - range = 8; - if ((range == 8) && (pi->port % 8)) - return 0; - pi->reserved = range; - return (!pi_test_proto(pi, scratch, verbose)); - } - best = -1; - for (pi->mode = 0; pi->mode < max; pi->mode++) { - range = 3; - if (pi->mode >= pi->proto->epp_first) - range = 8; - if ((range == 8) && (pi->port % 8)) - break; - pi->reserved = range; - if (!pi_test_proto(pi, scratch, verbose)) - best = pi->mode; - } - pi->mode = best; - return (best > -1); -} - -static int pi_probe_unit(PIA * pi, int unit, char *scratch, int verbose) -{ - int max, s, e; - - s = unit; - e = s + 1; - - if (s == -1) { - s = 0; - e = pi->proto->max_units; - } - - if (!pi_register_parport(pi, verbose, s)) - return 0; - - if (pi->proto->test_port) { - pi_claim(pi); - max = pi->proto->test_port(pi); - pi_unclaim(pi); - } else - max = pi->proto->max_mode; - - if (pi->proto->probe_unit) { - pi_claim(pi); - for (pi->unit = s; pi->unit < e; pi->unit++) - if (pi->proto->probe_unit(pi)) { - pi_unclaim(pi); - if (pi_probe_mode(pi, max, scratch, verbose)) - return 1; - pi_unregister_parport(pi); - return 0; - } - pi_unclaim(pi); - pi_unregister_parport(pi); - return 0; - } - - if (!pi_probe_mode(pi, max, scratch, verbose)) { - pi_unregister_parport(pi); - return 0; - } - return 1; - -} - -int pi_init(PIA * pi, int autoprobe, int port, int mode, - int unit, int protocol, int delay, char *scratch, - int devtype, int verbose, char *device) -{ - int p, k, s, e; - int lpts[7] = { 0x3bc, 0x378, 0x278, 0x268, 0x27c, 0x26c, 0 }; - - s = protocol; - e = s + 1; - - if (!protocols[0]) - request_module("paride_protocol"); - - if (autoprobe) { - s = 0; - e = MAX_PROTOS; - } else if ((s < 0) || (s >= MAX_PROTOS) || (port <= 0) || - (!protocols[s]) || (unit < 0) || - (unit >= protocols[s]->max_units)) { - printk("%s: Invalid parameters\n", device); - return 0; - } - - for (p = s; p < e; p++) { - struct pi_protocol *proto = protocols[p]; - if (!proto) - continue; - /* still racy */ - if (!try_module_get(proto->owner)) - continue; - pi->proto = proto; - pi->private = 0; - if (proto->init_proto && proto->init_proto(pi) < 0) { - pi->proto = NULL; - module_put(proto->owner); - continue; - } - if (delay == -1) - pi->delay = pi->proto->default_delay; - else - pi->delay = delay; - pi->devtype = devtype; - pi->device = device; - - pi->parname = NULL; - pi->pardev = NULL; - init_waitqueue_head(&pi->parq); - pi->claimed = 0; - pi->claim_cont = NULL; - - pi->mode = mode; - if (port != -1) { - pi->port = port; - if (pi_probe_unit(pi, unit, scratch, verbose)) - break; - pi->port = 0; - } else { - k = 0; - while ((pi->port = lpts[k++])) - if (pi_probe_unit - (pi, unit, scratch, verbose)) - break; - if (pi->port) - break; - } - if (pi->proto->release_proto) - pi->proto->release_proto(pi); - module_put(proto->owner); - } - - if (!pi->port) { - if (autoprobe) - printk("%s: Autoprobe failed\n", device); - else - printk("%s: Adapter not found\n", device); - return 0; - } - - if (pi->parname) - printk("%s: Sharing %s at 0x%x\n", pi->device, - pi->parname, pi->port); - - pi->proto->log_adapter(pi, scratch, verbose); - - return 1; -} - -EXPORT_SYMBOL(pi_init); - -static int pi_probe(struct pardevice *par_dev) -{ - struct device_driver *drv = par_dev->dev.driver; - int len = strlen(drv->name); - - if (strncmp(par_dev->name, drv->name, len)) - return -ENODEV; - - return 0; -} - -void *pi_register_driver(char *name) -{ - struct parport_driver *parp_drv; - int ret; - - parp_drv = kzalloc(sizeof(*parp_drv), GFP_KERNEL); - if (!parp_drv) - return NULL; - - parp_drv->name = name; - parp_drv->probe = pi_probe; - parp_drv->devmodel = true; - - ret = parport_register_driver(parp_drv); - if (ret) { - kfree(parp_drv); - return NULL; - } - return (void *)parp_drv; -} -EXPORT_SYMBOL(pi_register_driver); - -void pi_unregister_driver(void *_drv) -{ - struct parport_driver *drv = _drv; - - parport_unregister_driver(drv); - kfree(drv); -} -EXPORT_SYMBOL(pi_unregister_driver); diff --git a/drivers/block/paride/paride.h b/drivers/block/paride/paride.h deleted file mode 100644 index ddb9e589da7f..000000000000 --- a/drivers/block/paride/paride.h +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef __DRIVERS_PARIDE_H__ -#define __DRIVERS_PARIDE_H__ - -/* - paride.h (c) 1997-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GPL. - - This file defines the interface between the high-level parallel - IDE device drivers (pd, pf, pcd, pt) and the adapter chips. - -*/ - -/* Changes: - - 1.01 GRG 1998.05.05 init_proto, release_proto -*/ - -#define PARIDE_H_VERSION "1.01" - -/* Some adapters need to know what kind of device they are in - - Values for devtype: -*/ - -#define PI_PD 0 /* IDE disk */ -#define PI_PCD 1 /* ATAPI CDrom */ -#define PI_PF 2 /* ATAPI disk */ -#define PI_PT 3 /* ATAPI tape */ -#define PI_PG 4 /* ATAPI generic */ - -/* The paride module contains no state, instead the drivers allocate - a pi_adapter data structure and pass it to paride in every operation. - -*/ - -struct pi_adapter { - - struct pi_protocol *proto; /* adapter protocol */ - int port; /* base address of parallel port */ - int mode; /* transfer mode in use */ - int delay; /* adapter delay setting */ - int devtype; /* device type: PI_PD etc. */ - char *device; /* name of driver */ - int unit; /* unit number for chained adapters */ - int saved_r0; /* saved port state */ - int saved_r2; /* saved port state */ - int reserved; /* number of ports reserved */ - unsigned long private; /* for protocol module */ - - wait_queue_head_t parq; /* semaphore for parport sharing */ - void *pardev; /* pointer to pardevice */ - char *parname; /* parport name */ - int claimed; /* parport has already been claimed */ - void (*claim_cont)(void); /* continuation for parport wait */ -}; - -typedef struct pi_adapter PIA; - -/* functions exported by paride to the high level drivers */ - -extern int pi_init(PIA *pi, - int autoprobe, /* 1 to autoprobe */ - int port, /* base port address */ - int mode, /* -1 for autoprobe */ - int unit, /* unit number, if supported */ - int protocol, /* protocol to use */ - int delay, /* -1 to use adapter specific default */ - char * scratch, /* address of 512 byte buffer */ - int devtype, /* device type: PI_PD, PI_PCD, etc ... */ - int verbose, /* log verbose data while probing */ - char *device /* name of the driver */ - ); /* returns 0 on failure, 1 on success */ - -extern void pi_release(PIA *pi); - -/* registers are addressed as (cont,regr) - - cont: 0 for command register file, 1 for control register(s) - regr: 0-7 for register number. - -*/ - -extern void pi_write_regr(PIA *pi, int cont, int regr, int val); - -extern int pi_read_regr(PIA *pi, int cont, int regr); - -extern void pi_write_block(PIA *pi, char * buf, int count); - -extern void pi_read_block(PIA *pi, char * buf, int count); - -extern void pi_connect(PIA *pi); - -extern void pi_disconnect(PIA *pi); - -extern void pi_do_claimed(PIA *pi, void (*cont)(void)); -extern int pi_schedule_claimed(PIA *pi, void (*cont)(void)); - -/* macros and functions exported to the protocol modules */ - -#define delay_p (pi->delay?udelay(pi->delay):(void)0) -#define out_p(offs,byte) outb(byte,pi->port+offs); delay_p; -#define in_p(offs) (delay_p,inb(pi->port+offs)) - -#define w0(byte) {out_p(0,byte);} -#define r0() (in_p(0) & 0xff) -#define w1(byte) {out_p(1,byte);} -#define r1() (in_p(1) & 0xff) -#define w2(byte) {out_p(2,byte);} -#define r2() (in_p(2) & 0xff) -#define w3(byte) {out_p(3,byte);} -#define w4(byte) {out_p(4,byte);} -#define r4() (in_p(4) & 0xff) -#define w4w(data) {outw(data,pi->port+4); delay_p;} -#define w4l(data) {outl(data,pi->port+4); delay_p;} -#define r4w() (delay_p,inw(pi->port+4)&0xffff) -#define r4l() (delay_p,inl(pi->port+4)&0xffffffff) - -static inline u16 pi_swab16( char *b, int k) - -{ union { u16 u; char t[2]; } r; - - r.t[0]=b[2*k+1]; r.t[1]=b[2*k]; - return r.u; -} - -static inline u32 pi_swab32( char *b, int k) - -{ union { u32 u; char f[4]; } r; - - r.f[0]=b[4*k+1]; r.f[1]=b[4*k]; - r.f[2]=b[4*k+3]; r.f[3]=b[4*k+2]; - return r.u; -} - -struct pi_protocol { - - char name[8]; /* name for this protocol */ - int index; /* index into protocol table */ - - int max_mode; /* max mode number */ - int epp_first; /* modes >= this use 8 ports */ - - int default_delay; /* delay parameter if not specified */ - int max_units; /* max chained units probed for */ - - void (*write_regr)(PIA *,int,int,int); - int (*read_regr)(PIA *,int,int); - void (*write_block)(PIA *,char *,int); - void (*read_block)(PIA *,char *,int); - - void (*connect)(PIA *); - void (*disconnect)(PIA *); - - int (*test_port)(PIA *); - int (*probe_unit)(PIA *); - int (*test_proto)(PIA *,char *,int); - void (*log_adapter)(PIA *,char *,int); - - int (*init_proto)(PIA *); - void (*release_proto)(PIA *); - struct module *owner; -}; - -typedef struct pi_protocol PIP; - -extern int paride_register( PIP * ); -extern void paride_unregister ( PIP * ); -void *pi_register_driver(char *); -void pi_unregister_driver(void *); - -#endif /* __DRIVERS_PARIDE_H__ */ -/* end of paride.h */ diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c deleted file mode 100644 index a5ab40784119..000000000000 --- a/drivers/block/paride/pcd.c +++ /dev/null @@ -1,1042 +0,0 @@ -/* - pcd.c (c) 1997-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - This is a high-level driver for parallel port ATAPI CD-ROM - drives based on chips supported by the paride module. - - By default, the driver will autoprobe for a single parallel - port ATAPI CD-ROM drive, but if their individual parameters are - specified, the driver can handle up to 4 drives. - - The behaviour of the pcd driver can be altered by setting - some parameters from the insmod command line. The following - parameters are adjustable: - - drive0 These four arguments can be arrays of - drive1 1-6 integers as follows: - drive2 - drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<dly> - - Where, - - <prt> is the base of the parallel port address for - the corresponding drive. (required) - - <pro> is the protocol number for the adapter that - supports this drive. These numbers are - logged by 'paride' when the protocol modules - are initialised. (0 if not given) - - <uni> for those adapters that support chained - devices, this is the unit selector for the - chain of devices on the given port. It should - be zero for devices that don't support chaining. - (0 if not given) - - <mod> this can be -1 to choose the best mode, or one - of the mode numbers supported by the adapter. - (-1 if not given) - - <slv> ATAPI CD-ROMs can be jumpered to master or slave. - Set this to 0 to choose the master drive, 1 to - choose the slave, -1 (the default) to choose the - first drive found. - - <dly> some parallel ports require the driver to - go more slowly. -1 sets a default value that - should work with the chosen protocol. Otherwise, - set this to a small integer, the larger it is - the slower the port i/o. In some cases, setting - this to zero will speed up the device. (default -1) - - major You may use this parameter to override the - default major number (46) that this driver - will use. Be sure to change the device - name as well. - - name This parameter is a character string that - contains the name the kernel will use for this - device (in /proc output, for instance). - (default "pcd") - - verbose This parameter controls the amount of logging - that the driver will do. Set it to 0 for - normal operation, 1 to see autoprobe progress - messages, or 2 to see additional debugging - output. (default 0) - - nice This parameter controls the driver's use of - idle CPU time, at the expense of some speed. - - If this driver is built into the kernel, you can use the - following kernel command line parameters, with the same values - as the corresponding module parameters listed above: - - pcd.drive0 - pcd.drive1 - pcd.drive2 - pcd.drive3 - pcd.nice - - In addition, you can use the parameter pcd.disable to disable - the driver entirely. - -*/ - -/* Changes: - - 1.01 GRG 1998.01.24 Added test unit ready support - 1.02 GRG 1998.05.06 Changes to pcd_completion, ready_wait, - and loosen interpretation of ATAPI - standard for clearing error status. - Use spinlocks. Eliminate sti(). - 1.03 GRG 1998.06.16 Eliminated an Ugh - 1.04 GRG 1998.08.15 Added extra debugging, improvements to - pcd_completion, use HZ in loop timing - 1.05 GRG 1998.08.16 Conformed to "Uniform CD-ROM" standard - 1.06 GRG 1998.08.19 Added audio ioctl support - 1.07 GRG 1998.09.24 Increased reset timeout, added jumbo support - -*/ - -#define PCD_VERSION "1.07" -#define PCD_MAJOR 46 -#define PCD_NAME "pcd" -#define PCD_UNITS 4 - -/* Here are things one can override from the insmod command. - Most are autoprobed by paride unless set here. Verbose is off - by default. - -*/ - -static int verbose = 0; -static int major = PCD_MAJOR; -static char *name = PCD_NAME; -static int nice = 0; -static int disable = 0; - -static int drive0[6] = { 0, 0, 0, -1, -1, -1 }; -static int drive1[6] = { 0, 0, 0, -1, -1, -1 }; -static int drive2[6] = { 0, 0, 0, -1, -1, -1 }; -static int drive3[6] = { 0, 0, 0, -1, -1, -1 }; - -static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3}; -static int pcd_drive_count; - -enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY}; - -/* end of parameters */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/cdrom.h> -#include <linux/spinlock.h> -#include <linux/blk-mq.h> -#include <linux/mutex.h> -#include <linux/uaccess.h> - -static DEFINE_MUTEX(pcd_mutex); -static DEFINE_SPINLOCK(pcd_lock); - -module_param(verbose, int, 0644); -module_param(major, int, 0); -module_param(name, charp, 0); -module_param(nice, int, 0); -module_param_array(drive0, int, NULL, 0); -module_param_array(drive1, int, NULL, 0); -module_param_array(drive2, int, NULL, 0); -module_param_array(drive3, int, NULL, 0); - -#include "paride.h" -#include "pseudo.h" - -#define PCD_RETRIES 5 -#define PCD_TMO 800 /* timeout in jiffies */ -#define PCD_DELAY 50 /* spin delay in uS */ -#define PCD_READY_TMO 20 /* in seconds */ -#define PCD_RESET_TMO 100 /* in tenths of a second */ - -#define PCD_SPIN (1000000*PCD_TMO)/(HZ*PCD_DELAY) - -#define IDE_ERR 0x01 -#define IDE_DRQ 0x08 -#define IDE_READY 0x40 -#define IDE_BUSY 0x80 - -static int pcd_open(struct cdrom_device_info *cdi, int purpose); -static void pcd_release(struct cdrom_device_info *cdi); -static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr); -static unsigned int pcd_check_events(struct cdrom_device_info *cdi, - unsigned int clearing, int slot_nr); -static int pcd_tray_move(struct cdrom_device_info *cdi, int position); -static int pcd_lock_door(struct cdrom_device_info *cdi, int lock); -static int pcd_drive_reset(struct cdrom_device_info *cdi); -static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn); -static int pcd_audio_ioctl(struct cdrom_device_info *cdi, - unsigned int cmd, void *arg); -static int pcd_packet(struct cdrom_device_info *cdi, - struct packet_command *cgc); - -static void do_pcd_read_drq(void); -static blk_status_t pcd_queue_rq(struct blk_mq_hw_ctx *hctx, - const struct blk_mq_queue_data *bd); -static void do_pcd_read(void); - -struct pcd_unit { - struct pi_adapter pia; /* interface to paride layer */ - struct pi_adapter *pi; - int drive; /* master/slave */ - int last_sense; /* result of last request sense */ - int changed; /* media change seen */ - int present; /* does this unit exist ? */ - char *name; /* pcd0, pcd1, etc */ - struct cdrom_device_info info; /* uniform cdrom interface */ - struct gendisk *disk; - struct blk_mq_tag_set tag_set; - struct list_head rq_list; -}; - -static struct pcd_unit pcd[PCD_UNITS]; - -static char pcd_scratch[64]; -static char pcd_buffer[2048]; /* raw block buffer */ -static int pcd_bufblk = -1; /* block in buffer, in CD units, - -1 for nothing there. See also - pd_unit. - */ - -/* the variables below are used mainly in the I/O request engine, which - processes only one request at a time. -*/ - -static struct pcd_unit *pcd_current; /* current request's drive */ -static struct request *pcd_req; -static int pcd_retries; /* retries on current request */ -static int pcd_busy; /* request being processed ? */ -static int pcd_sector; /* address of next requested sector */ -static int pcd_count; /* number of blocks still to do */ -static char *pcd_buf; /* buffer for request in progress */ -static void *par_drv; /* reference of parport driver */ - -/* kernel glue structures */ - -static int pcd_block_open(struct block_device *bdev, fmode_t mode) -{ - struct pcd_unit *cd = bdev->bd_disk->private_data; - int ret; - - bdev_check_media_change(bdev); - - mutex_lock(&pcd_mutex); - ret = cdrom_open(&cd->info, bdev, mode); - mutex_unlock(&pcd_mutex); - - return ret; -} - -static void pcd_block_release(struct gendisk *disk, fmode_t mode) -{ - struct pcd_unit *cd = disk->private_data; - mutex_lock(&pcd_mutex); - cdrom_release(&cd->info, mode); - mutex_unlock(&pcd_mutex); -} - -static int pcd_block_ioctl(struct block_device *bdev, fmode_t mode, - unsigned cmd, unsigned long arg) -{ - struct pcd_unit *cd = bdev->bd_disk->private_data; - int ret; - - mutex_lock(&pcd_mutex); - ret = cdrom_ioctl(&cd->info, bdev, mode, cmd, arg); - mutex_unlock(&pcd_mutex); - - return ret; -} - -static unsigned int pcd_block_check_events(struct gendisk *disk, - unsigned int clearing) -{ - struct pcd_unit *cd = disk->private_data; - return cdrom_check_events(&cd->info, clearing); -} - -static const struct block_device_operations pcd_bdops = { - .owner = THIS_MODULE, - .open = pcd_block_open, - .release = pcd_block_release, - .ioctl = pcd_block_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = blkdev_compat_ptr_ioctl, -#endif - .check_events = pcd_block_check_events, -}; - -static const struct cdrom_device_ops pcd_dops = { - .open = pcd_open, - .release = pcd_release, - .drive_status = pcd_drive_status, - .check_events = pcd_check_events, - .tray_move = pcd_tray_move, - .lock_door = pcd_lock_door, - .get_mcn = pcd_get_mcn, - .reset = pcd_drive_reset, - .audio_ioctl = pcd_audio_ioctl, - .generic_packet = pcd_packet, - .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | - CDC_MCN | CDC_MEDIA_CHANGED | CDC_RESET | - CDC_PLAY_AUDIO | CDC_GENERIC_PACKET | CDC_CD_R | - CDC_CD_RW, -}; - -static const struct blk_mq_ops pcd_mq_ops = { - .queue_rq = pcd_queue_rq, -}; - -static int pcd_open(struct cdrom_device_info *cdi, int purpose) -{ - struct pcd_unit *cd = cdi->handle; - if (!cd->present) - return -ENODEV; - return 0; -} - -static void pcd_release(struct cdrom_device_info *cdi) -{ -} - -static inline int status_reg(struct pcd_unit *cd) -{ - return pi_read_regr(cd->pi, 1, 6); -} - -static inline int read_reg(struct pcd_unit *cd, int reg) -{ - return pi_read_regr(cd->pi, 0, reg); -} - -static inline void write_reg(struct pcd_unit *cd, int reg, int val) -{ - pi_write_regr(cd->pi, 0, reg, val); -} - -static int pcd_wait(struct pcd_unit *cd, int go, int stop, char *fun, char *msg) -{ - int j, r, e, s, p; - - j = 0; - while ((((r = status_reg(cd)) & go) || (stop && (!(r & stop)))) - && (j++ < PCD_SPIN)) - udelay(PCD_DELAY); - - if ((r & (IDE_ERR & stop)) || (j > PCD_SPIN)) { - s = read_reg(cd, 7); - e = read_reg(cd, 1); - p = read_reg(cd, 2); - if (j > PCD_SPIN) - e |= 0x100; - if (fun) - printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x" - " loop=%d phase=%d\n", - cd->name, fun, msg, r, s, e, j, p); - return (s << 8) + r; - } - return 0; -} - -static int pcd_command(struct pcd_unit *cd, char *cmd, int dlen, char *fun) -{ - pi_connect(cd->pi); - - write_reg(cd, 6, 0xa0 + 0x10 * cd->drive); - - if (pcd_wait(cd, IDE_BUSY | IDE_DRQ, 0, fun, "before command")) { - pi_disconnect(cd->pi); - return -1; - } - - write_reg(cd, 4, dlen % 256); - write_reg(cd, 5, dlen / 256); - write_reg(cd, 7, 0xa0); /* ATAPI packet command */ - - if (pcd_wait(cd, IDE_BUSY, IDE_DRQ, fun, "command DRQ")) { - pi_disconnect(cd->pi); - return -1; - } - - if (read_reg(cd, 2) != 1) { - printk("%s: %s: command phase error\n", cd->name, fun); - pi_disconnect(cd->pi); - return -1; - } - - pi_write_block(cd->pi, cmd, 12); - - return 0; -} - -static int pcd_completion(struct pcd_unit *cd, char *buf, char *fun) -{ - int r, d, p, n, k, j; - - r = -1; - k = 0; - j = 0; - - if (!pcd_wait(cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, - fun, "completion")) { - r = 0; - while (read_reg(cd, 7) & IDE_DRQ) { - d = read_reg(cd, 4) + 256 * read_reg(cd, 5); - n = (d + 3) & 0xfffc; - p = read_reg(cd, 2) & 3; - - if ((p == 2) && (n > 0) && (j == 0)) { - pi_read_block(cd->pi, buf, n); - if (verbose > 1) - printk("%s: %s: Read %d bytes\n", - cd->name, fun, n); - r = 0; - j++; - } else { - if (verbose > 1) - printk - ("%s: %s: Unexpected phase %d, d=%d, k=%d\n", - cd->name, fun, p, d, k); - if (verbose < 2) - printk_once( - "%s: WARNING: ATAPI phase errors\n", - cd->name); - mdelay(1); - } - if (k++ > PCD_TMO) { - printk("%s: Stuck DRQ\n", cd->name); - break; - } - if (pcd_wait - (cd, IDE_BUSY, IDE_DRQ | IDE_READY | IDE_ERR, fun, - "completion")) { - r = -1; - break; - } - } - } - - pi_disconnect(cd->pi); - - return r; -} - -static void pcd_req_sense(struct pcd_unit *cd, char *fun) -{ - char rs_cmd[12] = { 0x03, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 }; - char buf[16]; - int r, c; - - r = pcd_command(cd, rs_cmd, 16, "Request sense"); - mdelay(1); - if (!r) - pcd_completion(cd, buf, "Request sense"); - - cd->last_sense = -1; - c = 2; - if (!r) { - if (fun) - printk("%s: %s: Sense key: %x, ASC: %x, ASQ: %x\n", - cd->name, fun, buf[2] & 0xf, buf[12], buf[13]); - c = buf[2] & 0xf; - cd->last_sense = - c | ((buf[12] & 0xff) << 8) | ((buf[13] & 0xff) << 16); - } - if ((c == 2) || (c == 6)) - cd->changed = 1; -} - -static int pcd_atapi(struct pcd_unit *cd, char *cmd, int dlen, char *buf, char *fun) -{ - int r; - - r = pcd_command(cd, cmd, dlen, fun); - mdelay(1); - if (!r) - r = pcd_completion(cd, buf, fun); - if (r) - pcd_req_sense(cd, fun); - - return r; -} - -static int pcd_packet(struct cdrom_device_info *cdi, struct packet_command *cgc) -{ - return pcd_atapi(cdi->handle, cgc->cmd, cgc->buflen, cgc->buffer, - "generic packet"); -} - -#define DBMSG(msg) ((verbose>1)?(msg):NULL) - -static unsigned int pcd_check_events(struct cdrom_device_info *cdi, - unsigned int clearing, int slot_nr) -{ - struct pcd_unit *cd = cdi->handle; - int res = cd->changed; - if (res) - cd->changed = 0; - return res ? DISK_EVENT_MEDIA_CHANGE : 0; -} - -static int pcd_lock_door(struct cdrom_device_info *cdi, int lock) -{ - char un_cmd[12] = { 0x1e, 0, 0, 0, lock, 0, 0, 0, 0, 0, 0, 0 }; - - return pcd_atapi(cdi->handle, un_cmd, 0, pcd_scratch, - lock ? "lock door" : "unlock door"); -} - -static int pcd_tray_move(struct cdrom_device_info *cdi, int position) -{ - char ej_cmd[12] = { 0x1b, 0, 0, 0, 3 - position, 0, 0, 0, 0, 0, 0, 0 }; - - return pcd_atapi(cdi->handle, ej_cmd, 0, pcd_scratch, - position ? "eject" : "close tray"); -} - -static void pcd_sleep(int cs) -{ - schedule_timeout_interruptible(cs); -} - -static int pcd_reset(struct pcd_unit *cd) -{ - int i, k, flg; - int expect[5] = { 1, 1, 1, 0x14, 0xeb }; - - pi_connect(cd->pi); - write_reg(cd, 6, 0xa0 + 0x10 * cd->drive); - write_reg(cd, 7, 8); - - pcd_sleep(20 * HZ / 1000); /* delay a bit */ - - k = 0; - while ((k++ < PCD_RESET_TMO) && (status_reg(cd) & IDE_BUSY)) - pcd_sleep(HZ / 10); - - flg = 1; - for (i = 0; i < 5; i++) - flg &= (read_reg(cd, i + 1) == expect[i]); - - if (verbose) { - printk("%s: Reset (%d) signature = ", cd->name, k); - for (i = 0; i < 5; i++) - printk("%3x", read_reg(cd, i + 1)); - if (!flg) - printk(" (incorrect)"); - printk("\n"); - } - - pi_disconnect(cd->pi); - return flg - 1; -} - -static int pcd_drive_reset(struct cdrom_device_info *cdi) -{ - return pcd_reset(cdi->handle); -} - -static int pcd_ready_wait(struct pcd_unit *cd, int tmo) -{ - char tr_cmd[12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int k, p; - - k = 0; - while (k < tmo) { - cd->last_sense = 0; - pcd_atapi(cd, tr_cmd, 0, NULL, DBMSG("test unit ready")); - p = cd->last_sense; - if (!p) - return 0; - if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6))) - return p; - k++; - pcd_sleep(HZ); - } - return 0x000020; /* timeout */ -} - -static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr) -{ - char rc_cmd[12] = { 0x25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - struct pcd_unit *cd = cdi->handle; - - if (pcd_ready_wait(cd, PCD_READY_TMO)) - return CDS_DRIVE_NOT_READY; - if (pcd_atapi(cd, rc_cmd, 8, pcd_scratch, DBMSG("check media"))) - return CDS_NO_DISC; - return CDS_DISC_OK; -} - -static int pcd_identify(struct pcd_unit *cd) -{ - char id_cmd[12] = { 0x12, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 }; - char id[18]; - int k, s; - - pcd_bufblk = -1; - - s = pcd_atapi(cd, id_cmd, 36, pcd_buffer, "identify"); - - if (s) - return -1; - if ((pcd_buffer[0] & 0x1f) != 5) { - if (verbose) - printk("%s: %s is not a CD-ROM\n", - cd->name, cd->drive ? "Slave" : "Master"); - return -1; - } - memcpy(id, pcd_buffer + 16, 16); - id[16] = 0; - k = 16; - while ((k >= 0) && (id[k] <= 0x20)) { - id[k] = 0; - k--; - } - - printk("%s: %s: %s\n", cd->name, cd->drive ? "Slave" : "Master", id); - - return 0; -} - -/* - * returns 0, with id set if drive is detected, otherwise an error code. - */ -static int pcd_probe(struct pcd_unit *cd, int ms) -{ - if (ms == -1) { - for (cd->drive = 0; cd->drive <= 1; cd->drive++) - if (!pcd_reset(cd) && !pcd_identify(cd)) - return 0; - } else { - cd->drive = ms; - if (!pcd_reset(cd) && !pcd_identify(cd)) - return 0; - } - return -ENODEV; -} - -static int pcd_probe_capabilities(struct pcd_unit *cd) -{ - char cmd[12] = { 0x5a, 1 << 3, 0x2a, 0, 0, 0, 0, 18, 0, 0, 0, 0 }; - char buffer[32]; - int ret; - - ret = pcd_atapi(cd, cmd, 18, buffer, "mode sense capabilities"); - if (ret) - return ret; - - /* we should now have the cap page */ - if ((buffer[11] & 1) == 0) - cd->info.mask |= CDC_CD_R; - if ((buffer[11] & 2) == 0) - cd->info.mask |= CDC_CD_RW; - if ((buffer[12] & 1) == 0) - cd->info.mask |= CDC_PLAY_AUDIO; - if ((buffer[14] & 1) == 0) - cd->info.mask |= CDC_LOCK; - if ((buffer[14] & 8) == 0) - cd->info.mask |= CDC_OPEN_TRAY; - if ((buffer[14] >> 6) == 0) - cd->info.mask |= CDC_CLOSE_TRAY; - - return 0; -} - -/* I/O request processing */ -static int pcd_queue; - -static int set_next_request(void) -{ - struct pcd_unit *cd; - int old_pos = pcd_queue; - - do { - cd = &pcd[pcd_queue]; - if (++pcd_queue == PCD_UNITS) - pcd_queue = 0; - if (cd->present && !list_empty(&cd->rq_list)) { - pcd_req = list_first_entry(&cd->rq_list, struct request, - queuelist); - list_del_init(&pcd_req->queuelist); - blk_mq_start_request(pcd_req); - break; - } - } while (pcd_queue != old_pos); - - return pcd_req != NULL; -} - -static void pcd_request(void) -{ - struct pcd_unit *cd; - - if (pcd_busy) - return; - - if (!pcd_req && !set_next_request()) - return; - - cd = pcd_req->q->disk->private_data; - if (cd != pcd_current) - pcd_bufblk = -1; - pcd_current = cd; - pcd_sector = blk_rq_pos(pcd_req); - pcd_count = blk_rq_cur_sectors(pcd_req); - pcd_buf = bio_data(pcd_req->bio); - pcd_busy = 1; - ps_set_intr(do_pcd_read, NULL, 0, nice); -} - -static blk_status_t pcd_queue_rq(struct blk_mq_hw_ctx *hctx, - const struct blk_mq_queue_data *bd) -{ - struct pcd_unit *cd = hctx->queue->queuedata; - - if (rq_data_dir(bd->rq) != READ) { - blk_mq_start_request(bd->rq); - return BLK_STS_IOERR; - } - - spin_lock_irq(&pcd_lock); - list_add_tail(&bd->rq->queuelist, &cd->rq_list); - pcd_request(); - spin_unlock_irq(&pcd_lock); - - return BLK_STS_OK; -} - -static inline void next_request(blk_status_t err) -{ - unsigned long saved_flags; - - spin_lock_irqsave(&pcd_lock, saved_flags); - if (!blk_update_request(pcd_req, err, blk_rq_cur_bytes(pcd_req))) { - __blk_mq_end_request(pcd_req, err); - pcd_req = NULL; - } - pcd_busy = 0; - pcd_request(); - spin_unlock_irqrestore(&pcd_lock, saved_flags); -} - -static int pcd_ready(void) -{ - return (((status_reg(pcd_current) & (IDE_BUSY | IDE_DRQ)) == IDE_DRQ)); -} - -static void pcd_transfer(void) -{ - - while (pcd_count && (pcd_sector / 4 == pcd_bufblk)) { - int o = (pcd_sector % 4) * 512; - memcpy(pcd_buf, pcd_buffer + o, 512); - pcd_count--; - pcd_buf += 512; - pcd_sector++; - } -} - -static void pcd_start(void) -{ - int b, i; - char rd_cmd[12] = { 0xa8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; - - pcd_bufblk = pcd_sector / 4; - b = pcd_bufblk; - for (i = 0; i < 4; i++) { - rd_cmd[5 - i] = b & 0xff; - b = b >> 8; - } - - if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) { - pcd_bufblk = -1; - next_request(BLK_STS_IOERR); - return; - } - - mdelay(1); - - ps_set_intr(do_pcd_read_drq, pcd_ready, PCD_TMO, nice); -} - -static void do_pcd_read(void) -{ - pcd_busy = 1; - pcd_retries = 0; - pcd_transfer(); - if (!pcd_count) { - next_request(0); - return; - } - - pi_do_claimed(pcd_current->pi, pcd_start); -} - -static void do_pcd_read_drq(void) -{ - unsigned long saved_flags; - - if (pcd_completion(pcd_current, pcd_buffer, "read block")) { - if (pcd_retries < PCD_RETRIES) { - mdelay(1); - pcd_retries++; - pi_do_claimed(pcd_current->pi, pcd_start); - return; - } - pcd_bufblk = -1; - next_request(BLK_STS_IOERR); - return; - } - - do_pcd_read(); - spin_lock_irqsave(&pcd_lock, saved_flags); - pcd_request(); - spin_unlock_irqrestore(&pcd_lock, saved_flags); -} - -/* the audio_ioctl stuff is adapted from sr_ioctl.c */ - -static int pcd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, void *arg) -{ - struct pcd_unit *cd = cdi->handle; - - switch (cmd) { - - case CDROMREADTOCHDR: - - { - char cmd[12] = - { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12, - 0, 0, 0 }; - struct cdrom_tochdr *tochdr = - (struct cdrom_tochdr *) arg; - char buffer[32]; - int r; - - r = pcd_atapi(cd, cmd, 12, buffer, "read toc header"); - - tochdr->cdth_trk0 = buffer[2]; - tochdr->cdth_trk1 = buffer[3]; - - return r ? -EIO : 0; - } - - case CDROMREADTOCENTRY: - - { - char cmd[12] = - { GPCMD_READ_TOC_PMA_ATIP, 0, 0, 0, 0, 0, 0, 0, 12, - 0, 0, 0 }; - - struct cdrom_tocentry *tocentry = - (struct cdrom_tocentry *) arg; - unsigned char buffer[32]; - int r; - - cmd[1] = - (tocentry->cdte_format == CDROM_MSF ? 0x02 : 0); - cmd[6] = tocentry->cdte_track; - - r = pcd_atapi(cd, cmd, 12, buffer, "read toc entry"); - - tocentry->cdte_ctrl = buffer[5] & 0xf; - tocentry->cdte_adr = buffer[5] >> 4; - tocentry->cdte_datamode = - (tocentry->cdte_ctrl & 0x04) ? 1 : 0; - if (tocentry->cdte_format == CDROM_MSF) { - tocentry->cdte_addr.msf.minute = buffer[9]; - tocentry->cdte_addr.msf.second = buffer[10]; - tocentry->cdte_addr.msf.frame = buffer[11]; - } else - tocentry->cdte_addr.lba = - (((((buffer[8] << 8) + buffer[9]) << 8) - + buffer[10]) << 8) + buffer[11]; - - return r ? -EIO : 0; - } - - default: - - return -ENOSYS; - } -} - -static int pcd_get_mcn(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn) -{ - char cmd[12] = - { GPCMD_READ_SUBCHANNEL, 0, 0x40, 2, 0, 0, 0, 0, 24, 0, 0, 0 }; - char buffer[32]; - - if (pcd_atapi(cdi->handle, cmd, 24, buffer, "get mcn")) - return -EIO; - - memcpy(mcn->medium_catalog_number, buffer + 9, 13); - mcn->medium_catalog_number[13] = 0; - - return 0; -} - -static int pcd_init_unit(struct pcd_unit *cd, bool autoprobe, int port, - int mode, int unit, int protocol, int delay, int ms) -{ - struct gendisk *disk; - int ret; - - ret = blk_mq_alloc_sq_tag_set(&cd->tag_set, &pcd_mq_ops, 1, - BLK_MQ_F_SHOULD_MERGE); - if (ret) - return ret; - - disk = blk_mq_alloc_disk(&cd->tag_set, cd); - if (IS_ERR(disk)) { - ret = PTR_ERR(disk); - goto out_free_tag_set; - } - - INIT_LIST_HEAD(&cd->rq_list); - blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH); - cd->disk = disk; - cd->pi = &cd->pia; - cd->present = 0; - cd->last_sense = 0; - cd->changed = 1; - cd->drive = (*drives[cd - pcd])[D_SLV]; - - cd->name = &cd->info.name[0]; - snprintf(cd->name, sizeof(cd->info.name), "%s%d", name, unit); - cd->info.ops = &pcd_dops; - cd->info.handle = cd; - cd->info.speed = 0; - cd->info.capacity = 1; - cd->info.mask = 0; - disk->major = major; - disk->first_minor = unit; - disk->minors = 1; - strcpy(disk->disk_name, cd->name); /* umm... */ - disk->fops = &pcd_bdops; - disk->flags |= GENHD_FL_NO_PART; - disk->events = DISK_EVENT_MEDIA_CHANGE; - disk->event_flags = DISK_EVENT_FLAG_BLOCK_ON_EXCL_WRITE; - - if (!pi_init(cd->pi, autoprobe, port, mode, unit, protocol, delay, - pcd_buffer, PI_PCD, verbose, cd->name)) { - ret = -ENODEV; - goto out_free_disk; - } - ret = pcd_probe(cd, ms); - if (ret) - goto out_pi_release; - - cd->present = 1; - pcd_probe_capabilities(cd); - ret = register_cdrom(cd->disk, &cd->info); - if (ret) - goto out_pi_release; - ret = add_disk(cd->disk); - if (ret) - goto out_unreg_cdrom; - return 0; - -out_unreg_cdrom: - unregister_cdrom(&cd->info); -out_pi_release: - pi_release(cd->pi); -out_free_disk: - put_disk(cd->disk); -out_free_tag_set: - blk_mq_free_tag_set(&cd->tag_set); - return ret; -} - -static int __init pcd_init(void) -{ - int found = 0, unit; - - if (disable) - return -EINVAL; - - if (register_blkdev(major, name)) - return -EBUSY; - - pr_info("%s: %s version %s, major %d, nice %d\n", - name, name, PCD_VERSION, major, nice); - - par_drv = pi_register_driver(name); - if (!par_drv) { - pr_err("failed to register %s driver\n", name); - goto out_unregister_blkdev; - } - - for (unit = 0; unit < PCD_UNITS; unit++) { - if ((*drives[unit])[D_PRT]) - pcd_drive_count++; - } - - if (pcd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */ - if (!pcd_init_unit(pcd, 1, -1, -1, -1, -1, -1, -1)) - found++; - } else { - for (unit = 0; unit < PCD_UNITS; unit++) { - struct pcd_unit *cd = &pcd[unit]; - int *conf = *drives[unit]; - - if (!conf[D_PRT]) - continue; - if (!pcd_init_unit(cd, 0, conf[D_PRT], conf[D_MOD], - conf[D_UNI], conf[D_PRO], conf[D_DLY], - conf[D_SLV])) - found++; - } - } - - if (!found) { - pr_info("%s: No CD-ROM drive found\n", name); - goto out_unregister_pi_driver; - } - - return 0; - -out_unregister_pi_driver: - pi_unregister_driver(par_drv); -out_unregister_blkdev: - unregister_blkdev(major, name); - return -ENODEV; -} - -static void __exit pcd_exit(void) -{ - struct pcd_unit *cd; - int unit; - - for (unit = 0, cd = pcd; unit < PCD_UNITS; unit++, cd++) { - if (!cd->present) - continue; - - unregister_cdrom(&cd->info); - del_gendisk(cd->disk); - pi_release(cd->pi); - put_disk(cd->disk); - - blk_mq_free_tag_set(&cd->tag_set); - } - pi_unregister_driver(par_drv); - unregister_blkdev(major, name); -} - -MODULE_LICENSE("GPL"); -module_init(pcd_init) -module_exit(pcd_exit) diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c deleted file mode 100644 index f8a75bc90f70..000000000000 --- a/drivers/block/paride/pd.c +++ /dev/null @@ -1,1032 +0,0 @@ -/* - pd.c (c) 1997-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - This is the high-level driver for parallel port IDE hard - drives based on chips supported by the paride module. - - By default, the driver will autoprobe for a single parallel - port IDE drive, but if their individual parameters are - specified, the driver can handle up to 4 drives. - - The behaviour of the pd driver can be altered by setting - some parameters from the insmod command line. The following - parameters are adjustable: - - drive0 These four arguments can be arrays of - drive1 1-8 integers as follows: - drive2 - drive3 <prt>,<pro>,<uni>,<mod>,<geo>,<sby>,<dly>,<slv> - - Where, - - <prt> is the base of the parallel port address for - the corresponding drive. (required) - - <pro> is the protocol number for the adapter that - supports this drive. These numbers are - logged by 'paride' when the protocol modules - are initialised. (0 if not given) - - <uni> for those adapters that support chained - devices, this is the unit selector for the - chain of devices on the given port. It should - be zero for devices that don't support chaining. - (0 if not given) - - <mod> this can be -1 to choose the best mode, or one - of the mode numbers supported by the adapter. - (-1 if not given) - - <geo> this defaults to 0 to indicate that the driver - should use the CHS geometry provided by the drive - itself. If set to 1, the driver will provide - a logical geometry with 64 heads and 32 sectors - per track, to be consistent with most SCSI - drivers. (0 if not given) - - <sby> set this to zero to disable the power saving - standby mode, if needed. (1 if not given) - - <dly> some parallel ports require the driver to - go more slowly. -1 sets a default value that - should work with the chosen protocol. Otherwise, - set this to a small integer, the larger it is - the slower the port i/o. In some cases, setting - this to zero will speed up the device. (default -1) - - <slv> IDE disks can be jumpered to master or slave. - Set this to 0 to choose the master drive, 1 to - choose the slave, -1 (the default) to choose the - first drive found. - - - major You may use this parameter to override the - default major number (45) that this driver - will use. Be sure to change the device - name as well. - - name This parameter is a character string that - contains the name the kernel will use for this - device (in /proc output, for instance). - (default "pd") - - cluster The driver will attempt to aggregate requests - for adjacent blocks into larger multi-block - clusters. The maximum cluster size (in 512 - byte sectors) is set with this parameter. - (default 64) - - verbose This parameter controls the amount of logging - that the driver will do. Set it to 0 for - normal operation, 1 to see autoprobe progress - messages, or 2 to see additional debugging - output. (default 0) - - nice This parameter controls the driver's use of - idle CPU time, at the expense of some speed. - - If this driver is built into the kernel, you can use kernel - the following command line parameters, with the same values - as the corresponding module parameters listed above: - - pd.drive0 - pd.drive1 - pd.drive2 - pd.drive3 - pd.cluster - pd.nice - - In addition, you can use the parameter pd.disable to disable - the driver entirely. - -*/ - -/* Changes: - - 1.01 GRG 1997.01.24 Restored pd_reset() - Added eject ioctl - 1.02 GRG 1998.05.06 SMP spinlock changes, - Added slave support - 1.03 GRG 1998.06.16 Eliminate an Ugh. - 1.04 GRG 1998.08.15 Extra debugging, use HZ in loop timing - 1.05 GRG 1998.09.24 Added jumbo support - -*/ - -#define PD_VERSION "1.05" -#define PD_MAJOR 45 -#define PD_NAME "pd" -#define PD_UNITS 4 - -/* Here are things one can override from the insmod command. - Most are autoprobed by paride unless set here. Verbose is off - by default. - -*/ -#include <linux/types.h> - -static int verbose = 0; -static int major = PD_MAJOR; -static char *name = PD_NAME; -static int cluster = 64; -static int nice = 0; -static int disable = 0; - -static int drive0[8] = { 0, 0, 0, -1, 0, 1, -1, -1 }; -static int drive1[8] = { 0, 0, 0, -1, 0, 1, -1, -1 }; -static int drive2[8] = { 0, 0, 0, -1, 0, 1, -1, -1 }; -static int drive3[8] = { 0, 0, 0, -1, 0, 1, -1, -1 }; - -static int (*drives[4])[8] = {&drive0, &drive1, &drive2, &drive3}; - -enum {D_PRT, D_PRO, D_UNI, D_MOD, D_GEO, D_SBY, D_DLY, D_SLV}; - -/* end of parameters */ - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/gfp.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/hdreg.h> -#include <linux/cdrom.h> /* for the eject ioctl */ -#include <linux/blk-mq.h> -#include <linux/blkpg.h> -#include <linux/kernel.h> -#include <linux/mutex.h> -#include <linux/uaccess.h> -#include <linux/workqueue.h> - -static DEFINE_MUTEX(pd_mutex); -static DEFINE_SPINLOCK(pd_lock); - -module_param(verbose, int, 0); -module_param(major, int, 0); -module_param(name, charp, 0); -module_param(cluster, int, 0); -module_param(nice, int, 0); -module_param_array(drive0, int, NULL, 0); -module_param_array(drive1, int, NULL, 0); -module_param_array(drive2, int, NULL, 0); -module_param_array(drive3, int, NULL, 0); - -#include "paride.h" - -#define PD_BITS 4 - -/* numbers for "SCSI" geometry */ - -#define PD_LOG_HEADS 64 -#define PD_LOG_SECTS 32 - -#define PD_ID_OFF 54 -#define PD_ID_LEN 14 - -#define PD_MAX_RETRIES 5 -#define PD_TMO 800 /* interrupt timeout in jiffies */ -#define PD_SPIN_DEL 50 /* spin delay in micro-seconds */ - -#define PD_SPIN (1000000*PD_TMO)/(HZ*PD_SPIN_DEL) - -#define STAT_ERR 0x00001 -#define STAT_INDEX 0x00002 -#define STAT_ECC 0x00004 -#define STAT_DRQ 0x00008 -#define STAT_SEEK 0x00010 -#define STAT_WRERR 0x00020 -#define STAT_READY 0x00040 -#define STAT_BUSY 0x00080 - -#define ERR_AMNF 0x00100 -#define ERR_TK0NF 0x00200 -#define ERR_ABRT 0x00400 -#define ERR_MCR 0x00800 -#define ERR_IDNF 0x01000 -#define ERR_MC 0x02000 -#define ERR_UNC 0x04000 -#define ERR_TMO 0x10000 - -#define IDE_READ 0x20 -#define IDE_WRITE 0x30 -#define IDE_READ_VRFY 0x40 -#define IDE_INIT_DEV_PARMS 0x91 -#define IDE_STANDBY 0x96 -#define IDE_ACKCHANGE 0xdb -#define IDE_DOORLOCK 0xde -#define IDE_DOORUNLOCK 0xdf -#define IDE_IDENTIFY 0xec -#define IDE_EJECT 0xed - -#define PD_NAMELEN 8 - -struct pd_unit { - struct pi_adapter pia; /* interface to paride layer */ - struct pi_adapter *pi; - int access; /* count of active opens ... */ - int capacity; /* Size of this volume in sectors */ - int heads; /* physical geometry */ - int sectors; - int cylinders; - int can_lba; - int drive; /* master=0 slave=1 */ - int changed; /* Have we seen a disk change ? */ - int removable; /* removable media device ? */ - int standby; - int alt_geom; - char name[PD_NAMELEN]; /* pda, pdb, etc ... */ - struct gendisk *gd; - struct blk_mq_tag_set tag_set; - struct list_head rq_list; -}; - -static struct pd_unit pd[PD_UNITS]; - -struct pd_req { - /* for REQ_OP_DRV_IN: */ - enum action (*func)(struct pd_unit *disk); -}; - -static char pd_scratch[512]; /* scratch block buffer */ - -static char *pd_errs[17] = { "ERR", "INDEX", "ECC", "DRQ", "SEEK", "WRERR", - "READY", "BUSY", "AMNF", "TK0NF", "ABRT", "MCR", - "IDNF", "MC", "UNC", "???", "TMO" -}; - -static void *par_drv; /* reference of parport driver */ - -static inline int status_reg(struct pd_unit *disk) -{ - return pi_read_regr(disk->pi, 1, 6); -} - -static inline int read_reg(struct pd_unit *disk, int reg) -{ - return pi_read_regr(disk->pi, 0, reg); -} - -static inline void write_status(struct pd_unit *disk, int val) -{ - pi_write_regr(disk->pi, 1, 6, val); -} - -static inline void write_reg(struct pd_unit *disk, int reg, int val) -{ - pi_write_regr(disk->pi, 0, reg, val); -} - -static inline u8 DRIVE(struct pd_unit *disk) -{ - return 0xa0+0x10*disk->drive; -} - -/* ide command interface */ - -static void pd_print_error(struct pd_unit *disk, char *msg, int status) -{ - int i; - - printk("%s: %s: status = 0x%x =", disk->name, msg, status); - for (i = 0; i < ARRAY_SIZE(pd_errs); i++) - if (status & (1 << i)) - printk(" %s", pd_errs[i]); - printk("\n"); -} - -static void pd_reset(struct pd_unit *disk) -{ /* called only for MASTER drive */ - write_status(disk, 4); - udelay(50); - write_status(disk, 0); - udelay(250); -} - -#define DBMSG(msg) ((verbose>1)?(msg):NULL) - -static int pd_wait_for(struct pd_unit *disk, int w, char *msg) -{ /* polled wait */ - int k, r, e; - - k = 0; - while (k < PD_SPIN) { - r = status_reg(disk); - k++; - if (((r & w) == w) && !(r & STAT_BUSY)) - break; - udelay(PD_SPIN_DEL); - } - e = (read_reg(disk, 1) << 8) + read_reg(disk, 7); - if (k >= PD_SPIN) - e |= ERR_TMO; - if ((e & (STAT_ERR | ERR_TMO)) && (msg != NULL)) - pd_print_error(disk, msg, e); - return e; -} - -static void pd_send_command(struct pd_unit *disk, int n, int s, int h, int c0, int c1, int func) -{ - write_reg(disk, 6, DRIVE(disk) + h); - write_reg(disk, 1, 0); /* the IDE task file */ - write_reg(disk, 2, n); - write_reg(disk, 3, s); - write_reg(disk, 4, c0); - write_reg(disk, 5, c1); - write_reg(disk, 7, func); - - udelay(1); -} - -static void pd_ide_command(struct pd_unit *disk, int func, int block, int count) -{ - int c1, c0, h, s; - - if (disk->can_lba) { - s = block & 255; - c0 = (block >>= 8) & 255; - c1 = (block >>= 8) & 255; - h = ((block >>= 8) & 15) + 0x40; - } else { - s = (block % disk->sectors) + 1; - h = (block /= disk->sectors) % disk->heads; - c0 = (block /= disk->heads) % 256; - c1 = (block >>= 8); - } - pd_send_command(disk, count, s, h, c0, c1, func); -} - -/* The i/o request engine */ - -enum action {Fail = 0, Ok = 1, Hold, Wait}; - -static struct request *pd_req; /* current request */ -static enum action (*phase)(void); - -static void run_fsm(void); - -static void ps_tq_int(struct work_struct *work); - -static DECLARE_DELAYED_WORK(fsm_tq, ps_tq_int); - -static void schedule_fsm(void) -{ - if (!nice) - schedule_delayed_work(&fsm_tq, 0); - else - schedule_delayed_work(&fsm_tq, nice-1); -} - -static void ps_tq_int(struct work_struct *work) -{ - run_fsm(); -} - -static enum action do_pd_io_start(void); -static enum action pd_special(void); -static enum action do_pd_read_start(void); -static enum action do_pd_write_start(void); -static enum action do_pd_read_drq(void); -static enum action do_pd_write_done(void); - -static int pd_queue; -static int pd_claimed; - -static struct pd_unit *pd_current; /* current request's drive */ -static PIA *pi_current; /* current request's PIA */ - -static int set_next_request(void) -{ - struct gendisk *disk; - struct request_queue *q; - int old_pos = pd_queue; - - do { - disk = pd[pd_queue].gd; - q = disk ? disk->queue : NULL; - if (++pd_queue == PD_UNITS) - pd_queue = 0; - if (q) { - struct pd_unit *disk = q->queuedata; - - if (list_empty(&disk->rq_list)) - continue; - - pd_req = list_first_entry(&disk->rq_list, - struct request, - queuelist); - list_del_init(&pd_req->queuelist); - blk_mq_start_request(pd_req); - break; - } - } while (pd_queue != old_pos); - - return pd_req != NULL; -} - -static void run_fsm(void) -{ - while (1) { - enum action res; - int stop = 0; - - if (!phase) { - pd_current = pd_req->q->disk->private_data; - pi_current = pd_current->pi; - phase = do_pd_io_start; - } - - switch (pd_claimed) { - case 0: - pd_claimed = 1; - if (!pi_schedule_claimed(pi_current, run_fsm)) - return; - fallthrough; - case 1: - pd_claimed = 2; - pi_current->proto->connect(pi_current); - } - - switch(res = phase()) { - case Ok: case Fail: { - blk_status_t err; - - err = res == Ok ? 0 : BLK_STS_IOERR; - pi_disconnect(pi_current); - pd_claimed = 0; - phase = NULL; - spin_lock_irq(&pd_lock); - if (!blk_update_request(pd_req, err, - blk_rq_cur_bytes(pd_req))) { - __blk_mq_end_request(pd_req, err); - pd_req = NULL; - stop = !set_next_request(); - } - spin_unlock_irq(&pd_lock); - if (stop) - return; - } - fallthrough; - case Hold: - schedule_fsm(); - return; - case Wait: - pi_disconnect(pi_current); - pd_claimed = 0; - } - } -} - -static int pd_retries = 0; /* i/o error retry count */ -static int pd_block; /* address of next requested block */ -static int pd_count; /* number of blocks still to do */ -static int pd_run; /* sectors in current cluster */ -static char *pd_buf; /* buffer for request in progress */ - -static enum action do_pd_io_start(void) -{ - switch (req_op(pd_req)) { - case REQ_OP_DRV_IN: - phase = pd_special; - return pd_special(); - case REQ_OP_READ: - case REQ_OP_WRITE: - pd_block = blk_rq_pos(pd_req); - pd_count = blk_rq_cur_sectors(pd_req); - if (pd_block + pd_count > get_capacity(pd_req->q->disk)) - return Fail; - pd_run = blk_rq_sectors(pd_req); - pd_buf = bio_data(pd_req->bio); - pd_retries = 0; - if (req_op(pd_req) == REQ_OP_READ) - return do_pd_read_start(); - else - return do_pd_write_start(); - default: - break; - } - return Fail; -} - -static enum action pd_special(void) -{ - struct pd_req *req = blk_mq_rq_to_pdu(pd_req); - - return req->func(pd_current); -} - -static int pd_next_buf(void) -{ - unsigned long saved_flags; - - pd_count--; - pd_run--; - pd_buf += 512; - pd_block++; - if (!pd_run) - return 1; - if (pd_count) - return 0; - spin_lock_irqsave(&pd_lock, saved_flags); - if (!blk_update_request(pd_req, 0, blk_rq_cur_bytes(pd_req))) { - __blk_mq_end_request(pd_req, 0); - pd_req = NULL; - pd_count = 0; - pd_buf = NULL; - } else { - pd_count = blk_rq_cur_sectors(pd_req); - pd_buf = bio_data(pd_req->bio); - } - spin_unlock_irqrestore(&pd_lock, saved_flags); - return !pd_count; -} - -static unsigned long pd_timeout; - -static enum action do_pd_read_start(void) -{ - if (pd_wait_for(pd_current, STAT_READY, "do_pd_read") & STAT_ERR) { - if (pd_retries < PD_MAX_RETRIES) { - pd_retries++; - return Wait; - } - return Fail; - } - pd_ide_command(pd_current, IDE_READ, pd_block, pd_run); - phase = do_pd_read_drq; - pd_timeout = jiffies + PD_TMO; - return Hold; -} - -static enum action do_pd_write_start(void) -{ - if (pd_wait_for(pd_current, STAT_READY, "do_pd_write") & STAT_ERR) { - if (pd_retries < PD_MAX_RETRIES) { - pd_retries++; - return Wait; - } - return Fail; - } - pd_ide_command(pd_current, IDE_WRITE, pd_block, pd_run); - while (1) { - if (pd_wait_for(pd_current, STAT_DRQ, "do_pd_write_drq") & STAT_ERR) { - if (pd_retries < PD_MAX_RETRIES) { - pd_retries++; - return Wait; - } - return Fail; - } - pi_write_block(pd_current->pi, pd_buf, 512); - if (pd_next_buf()) - break; - } - phase = do_pd_write_done; - pd_timeout = jiffies + PD_TMO; - return Hold; -} - -static inline int pd_ready(void) -{ - return !(status_reg(pd_current) & STAT_BUSY); -} - -static enum action do_pd_read_drq(void) -{ - if (!pd_ready() && !time_after_eq(jiffies, pd_timeout)) - return Hold; - - while (1) { - if (pd_wait_for(pd_current, STAT_DRQ, "do_pd_read_drq") & STAT_ERR) { - if (pd_retries < PD_MAX_RETRIES) { - pd_retries++; - phase = do_pd_read_start; - return Wait; - } - return Fail; - } - pi_read_block(pd_current->pi, pd_buf, 512); - if (pd_next_buf()) - break; - } - return Ok; -} - -static enum action do_pd_write_done(void) -{ - if (!pd_ready() && !time_after_eq(jiffies, pd_timeout)) - return Hold; - - if (pd_wait_for(pd_current, STAT_READY, "do_pd_write_done") & STAT_ERR) { - if (pd_retries < PD_MAX_RETRIES) { - pd_retries++; - phase = do_pd_write_start; - return Wait; - } - return Fail; - } - return Ok; -} - -/* special io requests */ - -/* According to the ATA standard, the default CHS geometry should be - available following a reset. Some Western Digital drives come up - in a mode where only LBA addresses are accepted until the device - parameters are initialised. -*/ - -static void pd_init_dev_parms(struct pd_unit *disk) -{ - pd_wait_for(disk, 0, DBMSG("before init_dev_parms")); - pd_send_command(disk, disk->sectors, 0, disk->heads - 1, 0, 0, - IDE_INIT_DEV_PARMS); - udelay(300); - pd_wait_for(disk, 0, "Initialise device parameters"); -} - -static enum action pd_door_lock(struct pd_unit *disk) -{ - if (!(pd_wait_for(disk, STAT_READY, "Lock") & STAT_ERR)) { - pd_send_command(disk, 1, 0, 0, 0, 0, IDE_DOORLOCK); - pd_wait_for(disk, STAT_READY, "Lock done"); - } - return Ok; -} - -static enum action pd_door_unlock(struct pd_unit *disk) -{ - if (!(pd_wait_for(disk, STAT_READY, "Lock") & STAT_ERR)) { - pd_send_command(disk, 1, 0, 0, 0, 0, IDE_DOORUNLOCK); - pd_wait_for(disk, STAT_READY, "Lock done"); - } - return Ok; -} - -static enum action pd_eject(struct pd_unit *disk) -{ - pd_wait_for(disk, 0, DBMSG("before unlock on eject")); - pd_send_command(disk, 1, 0, 0, 0, 0, IDE_DOORUNLOCK); - pd_wait_for(disk, 0, DBMSG("after unlock on eject")); - pd_wait_for(disk, 0, DBMSG("before eject")); - pd_send_command(disk, 0, 0, 0, 0, 0, IDE_EJECT); - pd_wait_for(disk, 0, DBMSG("after eject")); - return Ok; -} - -static enum action pd_media_check(struct pd_unit *disk) -{ - int r = pd_wait_for(disk, STAT_READY, DBMSG("before media_check")); - if (!(r & STAT_ERR)) { - pd_send_command(disk, 1, 1, 0, 0, 0, IDE_READ_VRFY); - r = pd_wait_for(disk, STAT_READY, DBMSG("RDY after READ_VRFY")); - } else - disk->changed = 1; /* say changed if other error */ - if (r & ERR_MC) { - disk->changed = 1; - pd_send_command(disk, 1, 0, 0, 0, 0, IDE_ACKCHANGE); - pd_wait_for(disk, STAT_READY, DBMSG("RDY after ACKCHANGE")); - pd_send_command(disk, 1, 1, 0, 0, 0, IDE_READ_VRFY); - r = pd_wait_for(disk, STAT_READY, DBMSG("RDY after VRFY")); - } - return Ok; -} - -static void pd_standby_off(struct pd_unit *disk) -{ - pd_wait_for(disk, 0, DBMSG("before STANDBY")); - pd_send_command(disk, 0, 0, 0, 0, 0, IDE_STANDBY); - pd_wait_for(disk, 0, DBMSG("after STANDBY")); -} - -static enum action pd_identify(struct pd_unit *disk) -{ - int j; - char id[PD_ID_LEN + 1]; - -/* WARNING: here there may be dragons. reset() applies to both drives, - but we call it only on probing the MASTER. This should allow most - common configurations to work, but be warned that a reset can clear - settings on the SLAVE drive. -*/ - - if (disk->drive == 0) - pd_reset(disk); - - write_reg(disk, 6, DRIVE(disk)); - pd_wait_for(disk, 0, DBMSG("before IDENT")); - pd_send_command(disk, 1, 0, 0, 0, 0, IDE_IDENTIFY); - - if (pd_wait_for(disk, STAT_DRQ, DBMSG("IDENT DRQ")) & STAT_ERR) - return Fail; - pi_read_block(disk->pi, pd_scratch, 512); - disk->can_lba = pd_scratch[99] & 2; - disk->sectors = le16_to_cpu(*(__le16 *) (pd_scratch + 12)); - disk->heads = le16_to_cpu(*(__le16 *) (pd_scratch + 6)); - disk->cylinders = le16_to_cpu(*(__le16 *) (pd_scratch + 2)); - if (disk->can_lba) - disk->capacity = le32_to_cpu(*(__le32 *) (pd_scratch + 120)); - else - disk->capacity = disk->sectors * disk->heads * disk->cylinders; - - for (j = 0; j < PD_ID_LEN; j++) - id[j ^ 1] = pd_scratch[j + PD_ID_OFF]; - j = PD_ID_LEN - 1; - while ((j >= 0) && (id[j] <= 0x20)) - j--; - j++; - id[j] = 0; - - disk->removable = pd_scratch[0] & 0x80; - - printk("%s: %s, %s, %d blocks [%dM], (%d/%d/%d), %s media\n", - disk->name, id, - disk->drive ? "slave" : "master", - disk->capacity, disk->capacity / 2048, - disk->cylinders, disk->heads, disk->sectors, - disk->removable ? "removable" : "fixed"); - - if (disk->capacity) - pd_init_dev_parms(disk); - if (!disk->standby) - pd_standby_off(disk); - - return Ok; -} - -/* end of io request engine */ - -static blk_status_t pd_queue_rq(struct blk_mq_hw_ctx *hctx, - const struct blk_mq_queue_data *bd) -{ - struct pd_unit *disk = hctx->queue->queuedata; - - spin_lock_irq(&pd_lock); - if (!pd_req) { - pd_req = bd->rq; - blk_mq_start_request(pd_req); - } else - list_add_tail(&bd->rq->queuelist, &disk->rq_list); - spin_unlock_irq(&pd_lock); - - run_fsm(); - return BLK_STS_OK; -} - -static int pd_special_command(struct pd_unit *disk, - enum action (*func)(struct pd_unit *disk)) -{ - struct request *rq; - struct pd_req *req; - - rq = blk_mq_alloc_request(disk->gd->queue, REQ_OP_DRV_IN, 0); - if (IS_ERR(rq)) - return PTR_ERR(rq); - req = blk_mq_rq_to_pdu(rq); - - req->func = func; - blk_execute_rq(rq, false); - blk_mq_free_request(rq); - return 0; -} - -/* kernel glue structures */ - -static int pd_open(struct block_device *bdev, fmode_t mode) -{ - struct pd_unit *disk = bdev->bd_disk->private_data; - - mutex_lock(&pd_mutex); - disk->access++; - - if (disk->removable) { - pd_special_command(disk, pd_media_check); - pd_special_command(disk, pd_door_lock); - } - mutex_unlock(&pd_mutex); - return 0; -} - -static int pd_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct pd_unit *disk = bdev->bd_disk->private_data; - - if (disk->alt_geom) { - geo->heads = PD_LOG_HEADS; - geo->sectors = PD_LOG_SECTS; - geo->cylinders = disk->capacity / (geo->heads * geo->sectors); - } else { - geo->heads = disk->heads; - geo->sectors = disk->sectors; - geo->cylinders = disk->cylinders; - } - - return 0; -} - -static int pd_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - struct pd_unit *disk = bdev->bd_disk->private_data; - - switch (cmd) { - case CDROMEJECT: - mutex_lock(&pd_mutex); - if (disk->access == 1) - pd_special_command(disk, pd_eject); - mutex_unlock(&pd_mutex); - return 0; - default: - return -EINVAL; - } -} - -static void pd_release(struct gendisk *p, fmode_t mode) -{ - struct pd_unit *disk = p->private_data; - - mutex_lock(&pd_mutex); - if (!--disk->access && disk->removable) - pd_special_command(disk, pd_door_unlock); - mutex_unlock(&pd_mutex); -} - -static unsigned int pd_check_events(struct gendisk *p, unsigned int clearing) -{ - struct pd_unit *disk = p->private_data; - int r; - if (!disk->removable) - return 0; - pd_special_command(disk, pd_media_check); - r = disk->changed; - disk->changed = 0; - return r ? DISK_EVENT_MEDIA_CHANGE : 0; -} - -static const struct block_device_operations pd_fops = { - .owner = THIS_MODULE, - .open = pd_open, - .release = pd_release, - .ioctl = pd_ioctl, - .compat_ioctl = pd_ioctl, - .getgeo = pd_getgeo, - .check_events = pd_check_events, -}; - -/* probing */ - -static const struct blk_mq_ops pd_mq_ops = { - .queue_rq = pd_queue_rq, -}; - -static int pd_probe_drive(struct pd_unit *disk, int autoprobe, int port, - int mode, int unit, int protocol, int delay) -{ - int index = disk - pd; - int *parm = *drives[index]; - struct gendisk *p; - int ret; - - disk->pi = &disk->pia; - disk->access = 0; - disk->changed = 1; - disk->capacity = 0; - disk->drive = parm[D_SLV]; - snprintf(disk->name, PD_NAMELEN, "%s%c", name, 'a' + index); - disk->alt_geom = parm[D_GEO]; - disk->standby = parm[D_SBY]; - INIT_LIST_HEAD(&disk->rq_list); - - if (!pi_init(disk->pi, autoprobe, port, mode, unit, protocol, delay, - pd_scratch, PI_PD, verbose, disk->name)) - return -ENXIO; - - memset(&disk->tag_set, 0, sizeof(disk->tag_set)); - disk->tag_set.ops = &pd_mq_ops; - disk->tag_set.cmd_size = sizeof(struct pd_req); - disk->tag_set.nr_hw_queues = 1; - disk->tag_set.nr_maps = 1; - disk->tag_set.queue_depth = 2; - disk->tag_set.numa_node = NUMA_NO_NODE; - disk->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING; - ret = blk_mq_alloc_tag_set(&disk->tag_set); - if (ret) - goto pi_release; - - p = blk_mq_alloc_disk(&disk->tag_set, disk); - if (IS_ERR(p)) { - ret = PTR_ERR(p); - goto free_tag_set; - } - disk->gd = p; - - strcpy(p->disk_name, disk->name); - p->fops = &pd_fops; - p->major = major; - p->first_minor = (disk - pd) << PD_BITS; - p->minors = 1 << PD_BITS; - p->events = DISK_EVENT_MEDIA_CHANGE; - p->private_data = disk; - blk_queue_max_hw_sectors(p->queue, cluster); - blk_queue_bounce_limit(p->queue, BLK_BOUNCE_HIGH); - - if (disk->drive == -1) { - for (disk->drive = 0; disk->drive <= 1; disk->drive++) { - ret = pd_special_command(disk, pd_identify); - if (ret == 0) - break; - } - } else { - ret = pd_special_command(disk, pd_identify); - } - if (ret) - goto put_disk; - set_capacity(disk->gd, disk->capacity); - ret = add_disk(disk->gd); - if (ret) - goto cleanup_disk; - return 0; -cleanup_disk: - put_disk(disk->gd); -put_disk: - put_disk(p); - disk->gd = NULL; -free_tag_set: - blk_mq_free_tag_set(&disk->tag_set); -pi_release: - pi_release(disk->pi); - return ret; -} - -static int __init pd_init(void) -{ - int found = 0, unit, pd_drive_count = 0; - struct pd_unit *disk; - - if (disable) - return -ENODEV; - - if (register_blkdev(major, name)) - return -ENODEV; - - printk("%s: %s version %s, major %d, cluster %d, nice %d\n", - name, name, PD_VERSION, major, cluster, nice); - - par_drv = pi_register_driver(name); - if (!par_drv) { - pr_err("failed to register %s driver\n", name); - goto out_unregister_blkdev; - } - - for (unit = 0; unit < PD_UNITS; unit++) { - int *parm = *drives[unit]; - - if (parm[D_PRT]) - pd_drive_count++; - } - - if (pd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */ - if (!pd_probe_drive(pd, 1, -1, -1, -1, -1, -1)) - found++; - } else { - for (unit = 0, disk = pd; unit < PD_UNITS; unit++, disk++) { - int *parm = *drives[unit]; - if (!parm[D_PRT]) - continue; - if (!pd_probe_drive(disk, 0, parm[D_PRT], parm[D_MOD], - parm[D_UNI], parm[D_PRO], parm[D_DLY])) - found++; - } - } - if (!found) { - printk("%s: no valid drive found\n", name); - goto out_pi_unregister_driver; - } - - return 0; - -out_pi_unregister_driver: - pi_unregister_driver(par_drv); -out_unregister_blkdev: - unregister_blkdev(major, name); - return -ENODEV; -} - -static void __exit pd_exit(void) -{ - struct pd_unit *disk; - int unit; - unregister_blkdev(major, name); - for (unit = 0, disk = pd; unit < PD_UNITS; unit++, disk++) { - struct gendisk *p = disk->gd; - if (p) { - disk->gd = NULL; - del_gendisk(p); - put_disk(p); - blk_mq_free_tag_set(&disk->tag_set); - pi_release(disk->pi); - } - } -} - -MODULE_LICENSE("GPL"); -module_init(pd_init) -module_exit(pd_exit) diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c deleted file mode 100644 index eec1b9fde245..000000000000 --- a/drivers/block/paride/pf.c +++ /dev/null @@ -1,1057 +0,0 @@ -/* - pf.c (c) 1997-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - This is the high-level driver for parallel port ATAPI disk - drives based on chips supported by the paride module. - - By default, the driver will autoprobe for a single parallel - port ATAPI disk drive, but if their individual parameters are - specified, the driver can handle up to 4 drives. - - The behaviour of the pf driver can be altered by setting - some parameters from the insmod command line. The following - parameters are adjustable: - - drive0 These four arguments can be arrays of - drive1 1-7 integers as follows: - drive2 - drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<lun>,<dly> - - Where, - - <prt> is the base of the parallel port address for - the corresponding drive. (required) - - <pro> is the protocol number for the adapter that - supports this drive. These numbers are - logged by 'paride' when the protocol modules - are initialised. (0 if not given) - - <uni> for those adapters that support chained - devices, this is the unit selector for the - chain of devices on the given port. It should - be zero for devices that don't support chaining. - (0 if not given) - - <mod> this can be -1 to choose the best mode, or one - of the mode numbers supported by the adapter. - (-1 if not given) - - <slv> ATAPI CDroms can be jumpered to master or slave. - Set this to 0 to choose the master drive, 1 to - choose the slave, -1 (the default) to choose the - first drive found. - - <lun> Some ATAPI devices support multiple LUNs. - One example is the ATAPI PD/CD drive from - Matshita/Panasonic. This device has a - CD drive on LUN 0 and a PD drive on LUN 1. - By default, the driver will search for the - first LUN with a supported device. Set - this parameter to force it to use a specific - LUN. (default -1) - - <dly> some parallel ports require the driver to - go more slowly. -1 sets a default value that - should work with the chosen protocol. Otherwise, - set this to a small integer, the larger it is - the slower the port i/o. In some cases, setting - this to zero will speed up the device. (default -1) - - major You may use this parameter to override the - default major number (47) that this driver - will use. Be sure to change the device - name as well. - - name This parameter is a character string that - contains the name the kernel will use for this - device (in /proc output, for instance). - (default "pf"). - - cluster The driver will attempt to aggregate requests - for adjacent blocks into larger multi-block - clusters. The maximum cluster size (in 512 - byte sectors) is set with this parameter. - (default 64) - - verbose This parameter controls the amount of logging - that the driver will do. Set it to 0 for - normal operation, 1 to see autoprobe progress - messages, or 2 to see additional debugging - output. (default 0) - - nice This parameter controls the driver's use of - idle CPU time, at the expense of some speed. - - If this driver is built into the kernel, you can use the - following command line parameters, with the same values - as the corresponding module parameters listed above: - - pf.drive0 - pf.drive1 - pf.drive2 - pf.drive3 - pf.cluster - pf.nice - - In addition, you can use the parameter pf.disable to disable - the driver entirely. - -*/ - -/* Changes: - - 1.01 GRG 1998.05.03 Changes for SMP. Eliminate sti(). - Fix for drives that don't clear STAT_ERR - until after next CDB delivered. - Small change in pf_completion to round - up transfer size. - 1.02 GRG 1998.06.16 Eliminated an Ugh - 1.03 GRG 1998.08.16 Use HZ in loop timings, extra debugging - 1.04 GRG 1998.09.24 Added jumbo support - -*/ - -#define PF_VERSION "1.04" -#define PF_MAJOR 47 -#define PF_NAME "pf" -#define PF_UNITS 4 - -#include <linux/types.h> - -/* Here are things one can override from the insmod command. - Most are autoprobed by paride unless set here. Verbose is off - by default. - -*/ - -static bool verbose = 0; -static int major = PF_MAJOR; -static char *name = PF_NAME; -static int cluster = 64; -static int nice = 0; -static int disable = 0; - -static int drive0[7] = { 0, 0, 0, -1, -1, -1, -1 }; -static int drive1[7] = { 0, 0, 0, -1, -1, -1, -1 }; -static int drive2[7] = { 0, 0, 0, -1, -1, -1, -1 }; -static int drive3[7] = { 0, 0, 0, -1, -1, -1, -1 }; - -static int (*drives[4])[7] = {&drive0, &drive1, &drive2, &drive3}; -static int pf_drive_count; - -enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_LUN, D_DLY}; - -/* end of parameters */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/hdreg.h> -#include <linux/cdrom.h> -#include <linux/spinlock.h> -#include <linux/blk-mq.h> -#include <linux/blkpg.h> -#include <linux/mutex.h> -#include <linux/uaccess.h> - -static DEFINE_MUTEX(pf_mutex); -static DEFINE_SPINLOCK(pf_spin_lock); - -module_param(verbose, bool, 0644); -module_param(major, int, 0); -module_param(name, charp, 0); -module_param(cluster, int, 0); -module_param(nice, int, 0); -module_param_array(drive0, int, NULL, 0); -module_param_array(drive1, int, NULL, 0); -module_param_array(drive2, int, NULL, 0); -module_param_array(drive3, int, NULL, 0); - -#include "paride.h" -#include "pseudo.h" - -/* constants for faking geometry numbers */ - -#define PF_FD_MAX 8192 /* use FD geometry under this size */ -#define PF_FD_HDS 2 -#define PF_FD_SPT 18 -#define PF_HD_HDS 64 -#define PF_HD_SPT 32 - -#define PF_MAX_RETRIES 5 -#define PF_TMO 800 /* interrupt timeout in jiffies */ -#define PF_SPIN_DEL 50 /* spin delay in micro-seconds */ - -#define PF_SPIN (1000000*PF_TMO)/(HZ*PF_SPIN_DEL) - -#define STAT_ERR 0x00001 -#define STAT_INDEX 0x00002 -#define STAT_ECC 0x00004 -#define STAT_DRQ 0x00008 -#define STAT_SEEK 0x00010 -#define STAT_WRERR 0x00020 -#define STAT_READY 0x00040 -#define STAT_BUSY 0x00080 - -#define ATAPI_REQ_SENSE 0x03 -#define ATAPI_LOCK 0x1e -#define ATAPI_DOOR 0x1b -#define ATAPI_MODE_SENSE 0x5a -#define ATAPI_CAPACITY 0x25 -#define ATAPI_IDENTIFY 0x12 -#define ATAPI_READ_10 0x28 -#define ATAPI_WRITE_10 0x2a - -static int pf_open(struct block_device *bdev, fmode_t mode); -static blk_status_t pf_queue_rq(struct blk_mq_hw_ctx *hctx, - const struct blk_mq_queue_data *bd); -static int pf_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg); -static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo); - -static void pf_release(struct gendisk *disk, fmode_t mode); - -static void do_pf_read(void); -static void do_pf_read_start(void); -static void do_pf_write(void); -static void do_pf_write_start(void); -static void do_pf_read_drq(void); -static void do_pf_write_done(void); - -#define PF_NM 0 -#define PF_RO 1 -#define PF_RW 2 - -#define PF_NAMELEN 8 - -struct pf_unit { - struct pi_adapter pia; /* interface to paride layer */ - struct pi_adapter *pi; - int removable; /* removable media device ? */ - int media_status; /* media present ? WP ? */ - int drive; /* drive */ - int lun; - int access; /* count of active opens ... */ - int present; /* device present ? */ - char name[PF_NAMELEN]; /* pf0, pf1, ... */ - struct gendisk *disk; - struct blk_mq_tag_set tag_set; - struct list_head rq_list; -}; - -static struct pf_unit units[PF_UNITS]; - -static int pf_identify(struct pf_unit *pf); -static void pf_lock(struct pf_unit *pf, int func); -static void pf_eject(struct pf_unit *pf); -static unsigned int pf_check_events(struct gendisk *disk, - unsigned int clearing); - -static char pf_scratch[512]; /* scratch block buffer */ - -/* the variables below are used mainly in the I/O request engine, which - processes only one request at a time. -*/ - -static int pf_retries = 0; /* i/o error retry count */ -static int pf_busy = 0; /* request being processed ? */ -static struct request *pf_req; /* current request */ -static int pf_block; /* address of next requested block */ -static int pf_count; /* number of blocks still to do */ -static int pf_run; /* sectors in current cluster */ -static int pf_cmd; /* current command READ/WRITE */ -static struct pf_unit *pf_current;/* unit of current request */ -static int pf_mask; /* stopper for pseudo-int */ -static char *pf_buf; /* buffer for request in progress */ -static void *par_drv; /* reference of parport driver */ - -/* kernel glue structures */ - -static const struct block_device_operations pf_fops = { - .owner = THIS_MODULE, - .open = pf_open, - .release = pf_release, - .ioctl = pf_ioctl, - .compat_ioctl = pf_ioctl, - .getgeo = pf_getgeo, - .check_events = pf_check_events, -}; - -static const struct blk_mq_ops pf_mq_ops = { - .queue_rq = pf_queue_rq, -}; - -static int pf_open(struct block_device *bdev, fmode_t mode) -{ - struct pf_unit *pf = bdev->bd_disk->private_data; - int ret; - - mutex_lock(&pf_mutex); - pf_identify(pf); - - ret = -ENODEV; - if (pf->media_status == PF_NM) - goto out; - - ret = -EROFS; - if ((pf->media_status == PF_RO) && (mode & FMODE_WRITE)) - goto out; - - ret = 0; - pf->access++; - if (pf->removable) - pf_lock(pf, 1); -out: - mutex_unlock(&pf_mutex); - return ret; -} - -static int pf_getgeo(struct block_device *bdev, struct hd_geometry *geo) -{ - struct pf_unit *pf = bdev->bd_disk->private_data; - sector_t capacity = get_capacity(pf->disk); - - if (capacity < PF_FD_MAX) { - geo->cylinders = sector_div(capacity, PF_FD_HDS * PF_FD_SPT); - geo->heads = PF_FD_HDS; - geo->sectors = PF_FD_SPT; - } else { - geo->cylinders = sector_div(capacity, PF_HD_HDS * PF_HD_SPT); - geo->heads = PF_HD_HDS; - geo->sectors = PF_HD_SPT; - } - - return 0; -} - -static int pf_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg) -{ - struct pf_unit *pf = bdev->bd_disk->private_data; - - if (cmd != CDROMEJECT) - return -EINVAL; - - if (pf->access != 1) - return -EBUSY; - mutex_lock(&pf_mutex); - pf_eject(pf); - mutex_unlock(&pf_mutex); - - return 0; -} - -static void pf_release(struct gendisk *disk, fmode_t mode) -{ - struct pf_unit *pf = disk->private_data; - - mutex_lock(&pf_mutex); - if (pf->access <= 0) { - mutex_unlock(&pf_mutex); - WARN_ON(1); - return; - } - - pf->access--; - - if (!pf->access && pf->removable) - pf_lock(pf, 0); - - mutex_unlock(&pf_mutex); -} - -static unsigned int pf_check_events(struct gendisk *disk, unsigned int clearing) -{ - return DISK_EVENT_MEDIA_CHANGE; -} - -static inline int status_reg(struct pf_unit *pf) -{ - return pi_read_regr(pf->pi, 1, 6); -} - -static inline int read_reg(struct pf_unit *pf, int reg) -{ - return pi_read_regr(pf->pi, 0, reg); -} - -static inline void write_reg(struct pf_unit *pf, int reg, int val) -{ - pi_write_regr(pf->pi, 0, reg, val); -} - -static int pf_wait(struct pf_unit *pf, int go, int stop, char *fun, char *msg) -{ - int j, r, e, s, p; - - j = 0; - while ((((r = status_reg(pf)) & go) || (stop && (!(r & stop)))) - && (j++ < PF_SPIN)) - udelay(PF_SPIN_DEL); - - if ((r & (STAT_ERR & stop)) || (j > PF_SPIN)) { - s = read_reg(pf, 7); - e = read_reg(pf, 1); - p = read_reg(pf, 2); - if (j > PF_SPIN) - e |= 0x100; - if (fun) - printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x" - " loop=%d phase=%d\n", - pf->name, fun, msg, r, s, e, j, p); - return (e << 8) + s; - } - return 0; -} - -static int pf_command(struct pf_unit *pf, char *cmd, int dlen, char *fun) -{ - pi_connect(pf->pi); - - write_reg(pf, 6, 0xa0+0x10*pf->drive); - - if (pf_wait(pf, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) { - pi_disconnect(pf->pi); - return -1; - } - - write_reg(pf, 4, dlen % 256); - write_reg(pf, 5, dlen / 256); - write_reg(pf, 7, 0xa0); /* ATAPI packet command */ - - if (pf_wait(pf, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) { - pi_disconnect(pf->pi); - return -1; - } - - if (read_reg(pf, 2) != 1) { - printk("%s: %s: command phase error\n", pf->name, fun); - pi_disconnect(pf->pi); - return -1; - } - - pi_write_block(pf->pi, cmd, 12); - - return 0; -} - -static int pf_completion(struct pf_unit *pf, char *buf, char *fun) -{ - int r, s, n; - - r = pf_wait(pf, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR, - fun, "completion"); - - if ((read_reg(pf, 2) & 2) && (read_reg(pf, 7) & STAT_DRQ)) { - n = (((read_reg(pf, 4) + 256 * read_reg(pf, 5)) + - 3) & 0xfffc); - pi_read_block(pf->pi, buf, n); - } - - s = pf_wait(pf, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done"); - - pi_disconnect(pf->pi); - - return (r ? r : s); -} - -static void pf_req_sense(struct pf_unit *pf, int quiet) -{ - char rs_cmd[12] = - { ATAPI_REQ_SENSE, pf->lun << 5, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 }; - char buf[16]; - int r; - - r = pf_command(pf, rs_cmd, 16, "Request sense"); - mdelay(1); - if (!r) - pf_completion(pf, buf, "Request sense"); - - if ((!r) && (!quiet)) - printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n", - pf->name, buf[2] & 0xf, buf[12], buf[13]); -} - -static int pf_atapi(struct pf_unit *pf, char *cmd, int dlen, char *buf, char *fun) -{ - int r; - - r = pf_command(pf, cmd, dlen, fun); - mdelay(1); - if (!r) - r = pf_completion(pf, buf, fun); - if (r) - pf_req_sense(pf, !fun); - - return r; -} - -static void pf_lock(struct pf_unit *pf, int func) -{ - char lo_cmd[12] = { ATAPI_LOCK, pf->lun << 5, 0, 0, func, 0, 0, 0, 0, 0, 0, 0 }; - - pf_atapi(pf, lo_cmd, 0, pf_scratch, func ? "lock" : "unlock"); -} - -static void pf_eject(struct pf_unit *pf) -{ - char ej_cmd[12] = { ATAPI_DOOR, pf->lun << 5, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 }; - - pf_lock(pf, 0); - pf_atapi(pf, ej_cmd, 0, pf_scratch, "eject"); -} - -#define PF_RESET_TMO 30 /* in tenths of a second */ - -static void pf_sleep(int cs) -{ - schedule_timeout_interruptible(cs); -} - -/* the ATAPI standard actually specifies the contents of all 7 registers - after a reset, but the specification is ambiguous concerning the last - two bytes, and different drives interpret the standard differently. - */ - -static int pf_reset(struct pf_unit *pf) -{ - int i, k, flg; - int expect[5] = { 1, 1, 1, 0x14, 0xeb }; - - pi_connect(pf->pi); - write_reg(pf, 6, 0xa0+0x10*pf->drive); - write_reg(pf, 7, 8); - - pf_sleep(20 * HZ / 1000); - - k = 0; - while ((k++ < PF_RESET_TMO) && (status_reg(pf) & STAT_BUSY)) - pf_sleep(HZ / 10); - - flg = 1; - for (i = 0; i < 5; i++) - flg &= (read_reg(pf, i + 1) == expect[i]); - - if (verbose) { - printk("%s: Reset (%d) signature = ", pf->name, k); - for (i = 0; i < 5; i++) - printk("%3x", read_reg(pf, i + 1)); - if (!flg) - printk(" (incorrect)"); - printk("\n"); - } - - pi_disconnect(pf->pi); - return flg - 1; -} - -static void pf_mode_sense(struct pf_unit *pf) -{ - char ms_cmd[12] = - { ATAPI_MODE_SENSE, pf->lun << 5, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0 }; - char buf[8]; - - pf_atapi(pf, ms_cmd, 8, buf, "mode sense"); - pf->media_status = PF_RW; - if (buf[3] & 0x80) - pf->media_status = PF_RO; -} - -static void xs(char *buf, char *targ, int offs, int len) -{ - int j, k, l; - - j = 0; - l = 0; - for (k = 0; k < len; k++) - if ((buf[k + offs] != 0x20) || (buf[k + offs] != l)) - l = targ[j++] = buf[k + offs]; - if (l == 0x20) - j--; - targ[j] = 0; -} - -static int xl(char *buf, int offs) -{ - int v, k; - - v = 0; - for (k = 0; k < 4; k++) - v = v * 256 + (buf[k + offs] & 0xff); - return v; -} - -static void pf_get_capacity(struct pf_unit *pf) -{ - char rc_cmd[12] = { ATAPI_CAPACITY, pf->lun << 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - char buf[8]; - int bs; - - if (pf_atapi(pf, rc_cmd, 8, buf, "get capacity")) { - pf->media_status = PF_NM; - return; - } - set_capacity(pf->disk, xl(buf, 0) + 1); - bs = xl(buf, 4); - if (bs != 512) { - set_capacity(pf->disk, 0); - if (verbose) - printk("%s: Drive %d, LUN %d," - " unsupported block size %d\n", - pf->name, pf->drive, pf->lun, bs); - } -} - -static int pf_identify(struct pf_unit *pf) -{ - int dt, s; - char *ms[2] = { "master", "slave" }; - char mf[10], id[18]; - char id_cmd[12] = - { ATAPI_IDENTIFY, pf->lun << 5, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 }; - char buf[36]; - - s = pf_atapi(pf, id_cmd, 36, buf, "identify"); - if (s) - return -1; - - dt = buf[0] & 0x1f; - if ((dt != 0) && (dt != 7)) { - if (verbose) - printk("%s: Drive %d, LUN %d, unsupported type %d\n", - pf->name, pf->drive, pf->lun, dt); - return -1; - } - - xs(buf, mf, 8, 8); - xs(buf, id, 16, 16); - - pf->removable = (buf[1] & 0x80); - - pf_mode_sense(pf); - pf_mode_sense(pf); - pf_mode_sense(pf); - - pf_get_capacity(pf); - - printk("%s: %s %s, %s LUN %d, type %d", - pf->name, mf, id, ms[pf->drive], pf->lun, dt); - if (pf->removable) - printk(", removable"); - if (pf->media_status == PF_NM) - printk(", no media\n"); - else { - if (pf->media_status == PF_RO) - printk(", RO"); - printk(", %llu blocks\n", - (unsigned long long)get_capacity(pf->disk)); - } - return 0; -} - -/* - * returns 0, with id set if drive is detected, otherwise an error code. - */ -static int pf_probe(struct pf_unit *pf) -{ - if (pf->drive == -1) { - for (pf->drive = 0; pf->drive <= 1; pf->drive++) - if (!pf_reset(pf)) { - if (pf->lun != -1) - return pf_identify(pf); - else - for (pf->lun = 0; pf->lun < 8; pf->lun++) - if (!pf_identify(pf)) - return 0; - } - } else { - if (pf_reset(pf)) - return -1; - if (pf->lun != -1) - return pf_identify(pf); - for (pf->lun = 0; pf->lun < 8; pf->lun++) - if (!pf_identify(pf)) - return 0; - } - return -ENODEV; -} - -/* The i/o request engine */ - -static int pf_start(struct pf_unit *pf, int cmd, int b, int c) -{ - int i; - char io_cmd[12] = { cmd, pf->lun << 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - for (i = 0; i < 4; i++) { - io_cmd[5 - i] = b & 0xff; - b = b >> 8; - } - - io_cmd[8] = c & 0xff; - io_cmd[7] = (c >> 8) & 0xff; - - i = pf_command(pf, io_cmd, c * 512, "start i/o"); - - mdelay(1); - - return i; -} - -static int pf_ready(void) -{ - return (((status_reg(pf_current) & (STAT_BUSY | pf_mask)) == pf_mask)); -} - -static int pf_queue; - -static int set_next_request(void) -{ - struct pf_unit *pf; - int old_pos = pf_queue; - - do { - pf = &units[pf_queue]; - if (++pf_queue == PF_UNITS) - pf_queue = 0; - if (pf->present && !list_empty(&pf->rq_list)) { - pf_req = list_first_entry(&pf->rq_list, struct request, - queuelist); - list_del_init(&pf_req->queuelist); - blk_mq_start_request(pf_req); - break; - } - } while (pf_queue != old_pos); - - return pf_req != NULL; -} - -static void pf_end_request(blk_status_t err) -{ - if (!pf_req) - return; - if (!blk_update_request(pf_req, err, blk_rq_cur_bytes(pf_req))) { - __blk_mq_end_request(pf_req, err); - pf_req = NULL; - } -} - -static void pf_request(void) -{ - if (pf_busy) - return; -repeat: - if (!pf_req && !set_next_request()) - return; - - pf_current = pf_req->q->disk->private_data; - pf_block = blk_rq_pos(pf_req); - pf_run = blk_rq_sectors(pf_req); - pf_count = blk_rq_cur_sectors(pf_req); - - if (pf_block + pf_count > get_capacity(pf_req->q->disk)) { - pf_end_request(BLK_STS_IOERR); - goto repeat; - } - - pf_cmd = rq_data_dir(pf_req); - pf_buf = bio_data(pf_req->bio); - pf_retries = 0; - - pf_busy = 1; - if (pf_cmd == READ) - pi_do_claimed(pf_current->pi, do_pf_read); - else if (pf_cmd == WRITE) - pi_do_claimed(pf_current->pi, do_pf_write); - else { - pf_busy = 0; - pf_end_request(BLK_STS_IOERR); - goto repeat; - } -} - -static blk_status_t pf_queue_rq(struct blk_mq_hw_ctx *hctx, - const struct blk_mq_queue_data *bd) -{ - struct pf_unit *pf = hctx->queue->queuedata; - - spin_lock_irq(&pf_spin_lock); - list_add_tail(&bd->rq->queuelist, &pf->rq_list); - pf_request(); - spin_unlock_irq(&pf_spin_lock); - - return BLK_STS_OK; -} - -static int pf_next_buf(void) -{ - unsigned long saved_flags; - - pf_count--; - pf_run--; - pf_buf += 512; - pf_block++; - if (!pf_run) - return 1; - if (!pf_count) { - spin_lock_irqsave(&pf_spin_lock, saved_flags); - pf_end_request(0); - spin_unlock_irqrestore(&pf_spin_lock, saved_flags); - if (!pf_req) - return 1; - pf_count = blk_rq_cur_sectors(pf_req); - pf_buf = bio_data(pf_req->bio); - } - return 0; -} - -static inline void next_request(blk_status_t err) -{ - unsigned long saved_flags; - - spin_lock_irqsave(&pf_spin_lock, saved_flags); - pf_end_request(err); - pf_busy = 0; - pf_request(); - spin_unlock_irqrestore(&pf_spin_lock, saved_flags); -} - -/* detach from the calling context - in case the spinlock is held */ -static void do_pf_read(void) -{ - ps_set_intr(do_pf_read_start, NULL, 0, nice); -} - -static void do_pf_read_start(void) -{ - pf_busy = 1; - - if (pf_start(pf_current, ATAPI_READ_10, pf_block, pf_run)) { - pi_disconnect(pf_current->pi); - if (pf_retries < PF_MAX_RETRIES) { - pf_retries++; - pi_do_claimed(pf_current->pi, do_pf_read_start); - return; - } - next_request(BLK_STS_IOERR); - return; - } - pf_mask = STAT_DRQ; - ps_set_intr(do_pf_read_drq, pf_ready, PF_TMO, nice); -} - -static void do_pf_read_drq(void) -{ - while (1) { - if (pf_wait(pf_current, STAT_BUSY, STAT_DRQ | STAT_ERR, - "read block", "completion") & STAT_ERR) { - pi_disconnect(pf_current->pi); - if (pf_retries < PF_MAX_RETRIES) { - pf_req_sense(pf_current, 0); - pf_retries++; - pi_do_claimed(pf_current->pi, do_pf_read_start); - return; - } - next_request(BLK_STS_IOERR); - return; - } - pi_read_block(pf_current->pi, pf_buf, 512); - if (pf_next_buf()) - break; - } - pi_disconnect(pf_current->pi); - next_request(0); -} - -static void do_pf_write(void) -{ - ps_set_intr(do_pf_write_start, NULL, 0, nice); -} - -static void do_pf_write_start(void) -{ - pf_busy = 1; - - if (pf_start(pf_current, ATAPI_WRITE_10, pf_block, pf_run)) { - pi_disconnect(pf_current->pi); - if (pf_retries < PF_MAX_RETRIES) { - pf_retries++; - pi_do_claimed(pf_current->pi, do_pf_write_start); - return; - } - next_request(BLK_STS_IOERR); - return; - } - - while (1) { - if (pf_wait(pf_current, STAT_BUSY, STAT_DRQ | STAT_ERR, - "write block", "data wait") & STAT_ERR) { - pi_disconnect(pf_current->pi); - if (pf_retries < PF_MAX_RETRIES) { - pf_retries++; - pi_do_claimed(pf_current->pi, do_pf_write_start); - return; - } - next_request(BLK_STS_IOERR); - return; - } - pi_write_block(pf_current->pi, pf_buf, 512); - if (pf_next_buf()) - break; - } - pf_mask = 0; - ps_set_intr(do_pf_write_done, pf_ready, PF_TMO, nice); -} - -static void do_pf_write_done(void) -{ - if (pf_wait(pf_current, STAT_BUSY, 0, "write block", "done") & STAT_ERR) { - pi_disconnect(pf_current->pi); - if (pf_retries < PF_MAX_RETRIES) { - pf_retries++; - pi_do_claimed(pf_current->pi, do_pf_write_start); - return; - } - next_request(BLK_STS_IOERR); - return; - } - pi_disconnect(pf_current->pi); - next_request(0); -} - -static int __init pf_init_unit(struct pf_unit *pf, bool autoprobe, int port, - int mode, int unit, int protocol, int delay, int ms) -{ - struct gendisk *disk; - int ret; - - ret = blk_mq_alloc_sq_tag_set(&pf->tag_set, &pf_mq_ops, 1, - BLK_MQ_F_SHOULD_MERGE); - if (ret) - return ret; - - disk = blk_mq_alloc_disk(&pf->tag_set, pf); - if (IS_ERR(disk)) { - ret = PTR_ERR(disk); - goto out_free_tag_set; - } - disk->major = major; - disk->first_minor = pf - units; - disk->minors = 1; - strcpy(disk->disk_name, pf->name); - disk->fops = &pf_fops; - disk->flags |= GENHD_FL_NO_PART; - disk->events = DISK_EVENT_MEDIA_CHANGE; - disk->private_data = pf; - - blk_queue_max_segments(disk->queue, cluster); - blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH); - - INIT_LIST_HEAD(&pf->rq_list); - pf->disk = disk; - pf->pi = &pf->pia; - pf->media_status = PF_NM; - pf->drive = (*drives[disk->first_minor])[D_SLV]; - pf->lun = (*drives[disk->first_minor])[D_LUN]; - snprintf(pf->name, PF_NAMELEN, "%s%d", name, disk->first_minor); - - if (!pi_init(pf->pi, autoprobe, port, mode, unit, protocol, delay, - pf_scratch, PI_PF, verbose, pf->name)) { - ret = -ENODEV; - goto out_free_disk; - } - ret = pf_probe(pf); - if (ret) - goto out_pi_release; - - ret = add_disk(disk); - if (ret) - goto out_pi_release; - pf->present = 1; - return 0; - -out_pi_release: - pi_release(pf->pi); -out_free_disk: - put_disk(pf->disk); -out_free_tag_set: - blk_mq_free_tag_set(&pf->tag_set); - return ret; -} - -static int __init pf_init(void) -{ /* preliminary initialisation */ - struct pf_unit *pf; - int found = 0, unit; - - if (disable) - return -EINVAL; - - if (register_blkdev(major, name)) - return -EBUSY; - - printk("%s: %s version %s, major %d, cluster %d, nice %d\n", - name, name, PF_VERSION, major, cluster, nice); - - par_drv = pi_register_driver(name); - if (!par_drv) { - pr_err("failed to register %s driver\n", name); - goto out_unregister_blkdev; - } - - for (unit = 0; unit < PF_UNITS; unit++) { - if (!(*drives[unit])[D_PRT]) - pf_drive_count++; - } - - pf = units; - if (pf_drive_count == 0) { - if (pf_init_unit(pf, 1, -1, -1, -1, -1, -1, verbose)) - found++; - } else { - for (unit = 0; unit < PF_UNITS; unit++, pf++) { - int *conf = *drives[unit]; - if (!conf[D_PRT]) - continue; - if (pf_init_unit(pf, 0, conf[D_PRT], conf[D_MOD], - conf[D_UNI], conf[D_PRO], conf[D_DLY], - verbose)) - found++; - } - } - if (!found) { - printk("%s: No ATAPI disk detected\n", name); - goto out_unregister_pi_driver; - } - pf_busy = 0; - return 0; - -out_unregister_pi_driver: - pi_unregister_driver(par_drv); -out_unregister_blkdev: - unregister_blkdev(major, name); - return -ENODEV; -} - -static void __exit pf_exit(void) -{ - struct pf_unit *pf; - int unit; - - for (pf = units, unit = 0; unit < PF_UNITS; pf++, unit++) { - if (!pf->present) - continue; - del_gendisk(pf->disk); - put_disk(pf->disk); - blk_mq_free_tag_set(&pf->tag_set); - pi_release(pf->pi); - } - - unregister_blkdev(major, name); -} - -MODULE_LICENSE("GPL"); -module_init(pf_init) -module_exit(pf_exit) diff --git a/drivers/block/paride/pg.c b/drivers/block/paride/pg.c deleted file mode 100644 index 3b5882bfb736..000000000000 --- a/drivers/block/paride/pg.c +++ /dev/null @@ -1,734 +0,0 @@ -/* - pg.c (c) 1998 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - The pg driver provides a simple character device interface for - sending ATAPI commands to a device. With the exception of the - ATAPI reset operation, all operations are performed by a pair - of read and write operations to the appropriate /dev/pgN device. - A write operation delivers a command and any outbound data in - a single buffer. Normally, the write will succeed unless the - device is offline or malfunctioning, or there is already another - command pending. If the write succeeds, it should be followed - immediately by a read operation, to obtain any returned data and - status information. A read will fail if there is no operation - in progress. - - As a special case, the device can be reset with a write operation, - and in this case, no following read is expected, or permitted. - - There are no ioctl() operations. Any single operation - may transfer at most PG_MAX_DATA bytes. Note that the driver must - copy the data through an internal buffer. In keeping with all - current ATAPI devices, command packets are assumed to be exactly - 12 bytes in length. - - To permit future changes to this interface, the headers in the - read and write buffers contain a single character "magic" flag. - Currently this flag must be the character "P". - - By default, the driver will autoprobe for a single parallel - port ATAPI device, but if their individual parameters are - specified, the driver can handle up to 4 devices. - - To use this device, you must have the following device - special files defined: - - /dev/pg0 c 97 0 - /dev/pg1 c 97 1 - /dev/pg2 c 97 2 - /dev/pg3 c 97 3 - - (You'll need to change the 97 to something else if you use - the 'major' parameter to install the driver on a different - major number.) - - The behaviour of the pg driver can be altered by setting - some parameters from the insmod command line. The following - parameters are adjustable: - - drive0 These four arguments can be arrays of - drive1 1-6 integers as follows: - drive2 - drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<dly> - - Where, - - <prt> is the base of the parallel port address for - the corresponding drive. (required) - - <pro> is the protocol number for the adapter that - supports this drive. These numbers are - logged by 'paride' when the protocol modules - are initialised. (0 if not given) - - <uni> for those adapters that support chained - devices, this is the unit selector for the - chain of devices on the given port. It should - be zero for devices that don't support chaining. - (0 if not given) - - <mod> this can be -1 to choose the best mode, or one - of the mode numbers supported by the adapter. - (-1 if not given) - - <slv> ATAPI devices can be jumpered to master or slave. - Set this to 0 to choose the master drive, 1 to - choose the slave, -1 (the default) to choose the - first drive found. - - <dly> some parallel ports require the driver to - go more slowly. -1 sets a default value that - should work with the chosen protocol. Otherwise, - set this to a small integer, the larger it is - the slower the port i/o. In some cases, setting - this to zero will speed up the device. (default -1) - - major You may use this parameter to override the - default major number (97) that this driver - will use. Be sure to change the device - name as well. - - name This parameter is a character string that - contains the name the kernel will use for this - device (in /proc output, for instance). - (default "pg"). - - verbose This parameter controls the amount of logging - that is done by the driver. Set it to 0 for - quiet operation, to 1 to enable progress - messages while the driver probes for devices, - or to 2 for full debug logging. (default 0) - - If this driver is built into the kernel, you can use - the following command line parameters, with the same values - as the corresponding module parameters listed above: - - pg.drive0 - pg.drive1 - pg.drive2 - pg.drive3 - - In addition, you can use the parameter pg.disable to disable - the driver entirely. - -*/ - -/* Changes: - - 1.01 GRG 1998.06.16 Bug fixes - 1.02 GRG 1998.09.24 Added jumbo support - -*/ - -#define PG_VERSION "1.02" -#define PG_MAJOR 97 -#define PG_NAME "pg" -#define PG_UNITS 4 - -#ifndef PI_PG -#define PI_PG 4 -#endif - -#include <linux/types.h> -/* Here are things one can override from the insmod command. - Most are autoprobed by paride unless set here. Verbose is 0 - by default. - -*/ - -static int verbose; -static int major = PG_MAJOR; -static char *name = PG_NAME; -static int disable = 0; - -static int drive0[6] = { 0, 0, 0, -1, -1, -1 }; -static int drive1[6] = { 0, 0, 0, -1, -1, -1 }; -static int drive2[6] = { 0, 0, 0, -1, -1, -1 }; -static int drive3[6] = { 0, 0, 0, -1, -1, -1 }; - -static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3}; -static int pg_drive_count; - -enum {D_PRT, D_PRO, D_UNI, D_MOD, D_SLV, D_DLY}; - -/* end of parameters */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/mtio.h> -#include <linux/pg.h> -#include <linux/device.h> -#include <linux/sched.h> /* current, TASK_* */ -#include <linux/mutex.h> -#include <linux/jiffies.h> - -#include <linux/uaccess.h> - -module_param(verbose, int, 0644); -module_param(major, int, 0); -module_param(name, charp, 0); -module_param_array(drive0, int, NULL, 0); -module_param_array(drive1, int, NULL, 0); -module_param_array(drive2, int, NULL, 0); -module_param_array(drive3, int, NULL, 0); - -#include "paride.h" - -#define PG_SPIN_DEL 50 /* spin delay in micro-seconds */ -#define PG_SPIN 200 -#define PG_TMO HZ -#define PG_RESET_TMO 10*HZ - -#define STAT_ERR 0x01 -#define STAT_INDEX 0x02 -#define STAT_ECC 0x04 -#define STAT_DRQ 0x08 -#define STAT_SEEK 0x10 -#define STAT_WRERR 0x20 -#define STAT_READY 0x40 -#define STAT_BUSY 0x80 - -#define ATAPI_IDENTIFY 0x12 - -static DEFINE_MUTEX(pg_mutex); -static int pg_open(struct inode *inode, struct file *file); -static int pg_release(struct inode *inode, struct file *file); -static ssize_t pg_read(struct file *filp, char __user *buf, - size_t count, loff_t * ppos); -static ssize_t pg_write(struct file *filp, const char __user *buf, - size_t count, loff_t * ppos); -static int pg_detect(void); - -#define PG_NAMELEN 8 - -struct pg { - struct pi_adapter pia; /* interface to paride layer */ - struct pi_adapter *pi; - int busy; /* write done, read expected */ - int start; /* jiffies at command start */ - int dlen; /* transfer size requested */ - unsigned long timeout; /* timeout requested */ - int status; /* last sense key */ - int drive; /* drive */ - unsigned long access; /* count of active opens ... */ - int present; /* device present ? */ - char *bufptr; - char name[PG_NAMELEN]; /* pg0, pg1, ... */ -}; - -static struct pg devices[PG_UNITS]; - -static int pg_identify(struct pg *dev, int log); - -static char pg_scratch[512]; /* scratch block buffer */ - -static struct class *pg_class; -static void *par_drv; /* reference of parport driver */ - -/* kernel glue structures */ - -static const struct file_operations pg_fops = { - .owner = THIS_MODULE, - .read = pg_read, - .write = pg_write, - .open = pg_open, - .release = pg_release, - .llseek = noop_llseek, -}; - -static void pg_init_units(void) -{ - int unit; - - pg_drive_count = 0; - for (unit = 0; unit < PG_UNITS; unit++) { - int *parm = *drives[unit]; - struct pg *dev = &devices[unit]; - dev->pi = &dev->pia; - clear_bit(0, &dev->access); - dev->busy = 0; - dev->present = 0; - dev->bufptr = NULL; - dev->drive = parm[D_SLV]; - snprintf(dev->name, PG_NAMELEN, "%s%c", name, 'a'+unit); - if (parm[D_PRT]) - pg_drive_count++; - } -} - -static inline int status_reg(struct pg *dev) -{ - return pi_read_regr(dev->pi, 1, 6); -} - -static inline int read_reg(struct pg *dev, int reg) -{ - return pi_read_regr(dev->pi, 0, reg); -} - -static inline void write_reg(struct pg *dev, int reg, int val) -{ - pi_write_regr(dev->pi, 0, reg, val); -} - -static inline u8 DRIVE(struct pg *dev) -{ - return 0xa0+0x10*dev->drive; -} - -static void pg_sleep(int cs) -{ - schedule_timeout_interruptible(cs); -} - -static int pg_wait(struct pg *dev, int go, int stop, unsigned long tmo, char *msg) -{ - int j, r, e, s, p, to; - - dev->status = 0; - - j = 0; - while ((((r = status_reg(dev)) & go) || (stop && (!(r & stop)))) - && time_before(jiffies, tmo)) { - if (j++ < PG_SPIN) - udelay(PG_SPIN_DEL); - else - pg_sleep(1); - } - - to = time_after_eq(jiffies, tmo); - - if ((r & (STAT_ERR & stop)) || to) { - s = read_reg(dev, 7); - e = read_reg(dev, 1); - p = read_reg(dev, 2); - if (verbose > 1) - printk("%s: %s: stat=0x%x err=0x%x phase=%d%s\n", - dev->name, msg, s, e, p, to ? " timeout" : ""); - if (to) - e |= 0x100; - dev->status = (e >> 4) & 0xff; - return -1; - } - return 0; -} - -static int pg_command(struct pg *dev, char *cmd, int dlen, unsigned long tmo) -{ - int k; - - pi_connect(dev->pi); - - write_reg(dev, 6, DRIVE(dev)); - - if (pg_wait(dev, STAT_BUSY | STAT_DRQ, 0, tmo, "before command")) - goto fail; - - write_reg(dev, 4, dlen % 256); - write_reg(dev, 5, dlen / 256); - write_reg(dev, 7, 0xa0); /* ATAPI packet command */ - - if (pg_wait(dev, STAT_BUSY, STAT_DRQ, tmo, "command DRQ")) - goto fail; - - if (read_reg(dev, 2) != 1) { - printk("%s: command phase error\n", dev->name); - goto fail; - } - - pi_write_block(dev->pi, cmd, 12); - - if (verbose > 1) { - printk("%s: Command sent, dlen=%d packet= ", dev->name, dlen); - for (k = 0; k < 12; k++) - printk("%02x ", cmd[k] & 0xff); - printk("\n"); - } - return 0; -fail: - pi_disconnect(dev->pi); - return -1; -} - -static int pg_completion(struct pg *dev, char *buf, unsigned long tmo) -{ - int r, d, n, p; - - r = pg_wait(dev, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR, - tmo, "completion"); - - dev->dlen = 0; - - while (read_reg(dev, 7) & STAT_DRQ) { - d = (read_reg(dev, 4) + 256 * read_reg(dev, 5)); - n = ((d + 3) & 0xfffc); - p = read_reg(dev, 2) & 3; - if (p == 0) - pi_write_block(dev->pi, buf, n); - if (p == 2) - pi_read_block(dev->pi, buf, n); - if (verbose > 1) - printk("%s: %s %d bytes\n", dev->name, - p ? "Read" : "Write", n); - dev->dlen += (1 - p) * d; - buf += d; - r = pg_wait(dev, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR, - tmo, "completion"); - } - - pi_disconnect(dev->pi); - - return r; -} - -static int pg_reset(struct pg *dev) -{ - int i, k, err; - int expect[5] = { 1, 1, 1, 0x14, 0xeb }; - int got[5]; - - pi_connect(dev->pi); - write_reg(dev, 6, DRIVE(dev)); - write_reg(dev, 7, 8); - - pg_sleep(20 * HZ / 1000); - - k = 0; - while ((k++ < PG_RESET_TMO) && (status_reg(dev) & STAT_BUSY)) - pg_sleep(1); - - for (i = 0; i < 5; i++) - got[i] = read_reg(dev, i + 1); - - err = memcmp(expect, got, sizeof(got)) ? -1 : 0; - - if (verbose) { - printk("%s: Reset (%d) signature = ", dev->name, k); - for (i = 0; i < 5; i++) - printk("%3x", got[i]); - if (err) - printk(" (incorrect)"); - printk("\n"); - } - - pi_disconnect(dev->pi); - return err; -} - -static void xs(char *buf, char *targ, int len) -{ - char l = '\0'; - int k; - - for (k = 0; k < len; k++) { - char c = *buf++; - if (c != ' ' && c != l) - l = *targ++ = c; - } - if (l == ' ') - targ--; - *targ = '\0'; -} - -static int pg_identify(struct pg *dev, int log) -{ - int s; - char *ms[2] = { "master", "slave" }; - char mf[10], id[18]; - char id_cmd[12] = { ATAPI_IDENTIFY, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 }; - char buf[36]; - - s = pg_command(dev, id_cmd, 36, jiffies + PG_TMO); - if (s) - return -1; - s = pg_completion(dev, buf, jiffies + PG_TMO); - if (s) - return -1; - - if (log) { - xs(buf + 8, mf, 8); - xs(buf + 16, id, 16); - printk("%s: %s %s, %s\n", dev->name, mf, id, ms[dev->drive]); - } - - return 0; -} - -/* - * returns 0, with id set if drive is detected - * -1, if drive detection failed - */ -static int pg_probe(struct pg *dev) -{ - if (dev->drive == -1) { - for (dev->drive = 0; dev->drive <= 1; dev->drive++) - if (!pg_reset(dev)) - return pg_identify(dev, 1); - } else { - if (!pg_reset(dev)) - return pg_identify(dev, 1); - } - return -1; -} - -static int pg_detect(void) -{ - struct pg *dev = &devices[0]; - int k, unit; - - printk("%s: %s version %s, major %d\n", name, name, PG_VERSION, major); - - par_drv = pi_register_driver(name); - if (!par_drv) { - pr_err("failed to register %s driver\n", name); - return -1; - } - - k = 0; - if (pg_drive_count == 0) { - if (pi_init(dev->pi, 1, -1, -1, -1, -1, -1, pg_scratch, - PI_PG, verbose, dev->name)) { - if (!pg_probe(dev)) { - dev->present = 1; - k++; - } else - pi_release(dev->pi); - } - - } else - for (unit = 0; unit < PG_UNITS; unit++, dev++) { - int *parm = *drives[unit]; - if (!parm[D_PRT]) - continue; - if (pi_init(dev->pi, 0, parm[D_PRT], parm[D_MOD], - parm[D_UNI], parm[D_PRO], parm[D_DLY], - pg_scratch, PI_PG, verbose, dev->name)) { - if (!pg_probe(dev)) { - dev->present = 1; - k++; - } else - pi_release(dev->pi); - } - } - - if (k) - return 0; - - pi_unregister_driver(par_drv); - printk("%s: No ATAPI device detected\n", name); - return -1; -} - -static int pg_open(struct inode *inode, struct file *file) -{ - int unit = iminor(inode) & 0x7f; - struct pg *dev = &devices[unit]; - int ret = 0; - - mutex_lock(&pg_mutex); - if ((unit >= PG_UNITS) || (!dev->present)) { - ret = -ENODEV; - goto out; - } - - if (test_and_set_bit(0, &dev->access)) { - ret = -EBUSY; - goto out; - } - - if (dev->busy) { - pg_reset(dev); - dev->busy = 0; - } - - pg_identify(dev, (verbose > 1)); - - dev->bufptr = kmalloc(PG_MAX_DATA, GFP_KERNEL); - if (dev->bufptr == NULL) { - clear_bit(0, &dev->access); - printk("%s: buffer allocation failed\n", dev->name); - ret = -ENOMEM; - goto out; - } - - file->private_data = dev; - -out: - mutex_unlock(&pg_mutex); - return ret; -} - -static int pg_release(struct inode *inode, struct file *file) -{ - struct pg *dev = file->private_data; - - kfree(dev->bufptr); - dev->bufptr = NULL; - clear_bit(0, &dev->access); - - return 0; -} - -static ssize_t pg_write(struct file *filp, const char __user *buf, size_t count, loff_t *ppos) -{ - struct pg *dev = filp->private_data; - struct pg_write_hdr hdr; - int hs = sizeof (hdr); - - if (dev->busy) - return -EBUSY; - if (count < hs) - return -EINVAL; - - if (copy_from_user(&hdr, buf, hs)) - return -EFAULT; - - if (hdr.magic != PG_MAGIC) - return -EINVAL; - if (hdr.dlen < 0 || hdr.dlen > PG_MAX_DATA) - return -EINVAL; - if ((count - hs) > PG_MAX_DATA) - return -EINVAL; - - if (hdr.func == PG_RESET) { - if (count != hs) - return -EINVAL; - if (pg_reset(dev)) - return -EIO; - return count; - } - - if (hdr.func != PG_COMMAND) - return -EINVAL; - - dev->start = jiffies; - dev->timeout = hdr.timeout * HZ + HZ / 2 + jiffies; - - if (pg_command(dev, hdr.packet, hdr.dlen, jiffies + PG_TMO)) { - if (dev->status & 0x10) - return -ETIME; - return -EIO; - } - - dev->busy = 1; - - if (copy_from_user(dev->bufptr, buf + hs, count - hs)) - return -EFAULT; - return count; -} - -static ssize_t pg_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos) -{ - struct pg *dev = filp->private_data; - struct pg_read_hdr hdr; - int hs = sizeof (hdr); - int copy; - - if (!dev->busy) - return -EINVAL; - if (count < hs) - return -EINVAL; - - dev->busy = 0; - - if (pg_completion(dev, dev->bufptr, dev->timeout)) - if (dev->status & 0x10) - return -ETIME; - - memset(&hdr, 0, sizeof(hdr)); - hdr.magic = PG_MAGIC; - hdr.dlen = dev->dlen; - copy = 0; - - if (hdr.dlen < 0) { - hdr.dlen = -1 * hdr.dlen; - copy = hdr.dlen; - if (copy > (count - hs)) - copy = count - hs; - } - - hdr.duration = (jiffies - dev->start + HZ / 2) / HZ; - hdr.scsi = dev->status & 0x0f; - - if (copy_to_user(buf, &hdr, hs)) - return -EFAULT; - if (copy > 0) - if (copy_to_user(buf + hs, dev->bufptr, copy)) - return -EFAULT; - return copy + hs; -} - -static int __init pg_init(void) -{ - int unit; - int err; - - if (disable){ - err = -EINVAL; - goto out; - } - - pg_init_units(); - - if (pg_detect()) { - err = -ENODEV; - goto out; - } - - err = register_chrdev(major, name, &pg_fops); - if (err < 0) { - printk("pg_init: unable to get major number %d\n", major); - for (unit = 0; unit < PG_UNITS; unit++) { - struct pg *dev = &devices[unit]; - if (dev->present) - pi_release(dev->pi); - } - goto out; - } - major = err; /* In case the user specified `major=0' (dynamic) */ - pg_class = class_create(THIS_MODULE, "pg"); - if (IS_ERR(pg_class)) { - err = PTR_ERR(pg_class); - goto out_chrdev; - } - for (unit = 0; unit < PG_UNITS; unit++) { - struct pg *dev = &devices[unit]; - if (dev->present) - device_create(pg_class, NULL, MKDEV(major, unit), NULL, - "pg%u", unit); - } - err = 0; - goto out; - -out_chrdev: - unregister_chrdev(major, "pg"); -out: - return err; -} - -static void __exit pg_exit(void) -{ - int unit; - - for (unit = 0; unit < PG_UNITS; unit++) { - struct pg *dev = &devices[unit]; - if (dev->present) - device_destroy(pg_class, MKDEV(major, unit)); - } - class_destroy(pg_class); - unregister_chrdev(major, name); - - for (unit = 0; unit < PG_UNITS; unit++) { - struct pg *dev = &devices[unit]; - if (dev->present) - pi_release(dev->pi); - } -} - -MODULE_LICENSE("GPL"); -module_init(pg_init) -module_exit(pg_exit) diff --git a/drivers/block/paride/pseudo.h b/drivers/block/paride/pseudo.h deleted file mode 100644 index bc3703294143..000000000000 --- a/drivers/block/paride/pseudo.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - pseudo.h (c) 1997-8 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - This is the "pseudo-interrupt" logic for parallel port drivers. - - This module is #included into each driver. It makes one - function available: - - ps_set_intr( void (*continuation)(void), - int (*ready)(void), - int timeout, - int nice ) - - Which will arrange for ready() to be evaluated frequently and - when either it returns true, or timeout jiffies have passed, - continuation() will be invoked. - - If nice is 1, the test will done approximately once a - jiffy. If nice is 0, the test will also be done whenever - the scheduler runs (by adding it to a task queue). If - nice is greater than 1, the test will be done once every - (nice-1) jiffies. - -*/ - -/* Changes: - - 1.01 1998.05.03 Switched from cli()/sti() to spinlocks - 1.02 1998.12.14 Added support for nice > 1 -*/ - -#define PS_VERSION "1.02" - -#include <linux/sched.h> -#include <linux/workqueue.h> - -static void ps_tq_int(struct work_struct *work); - -static void (* ps_continuation)(void); -static int (* ps_ready)(void); -static unsigned long ps_timeout; -static int ps_tq_active = 0; -static int ps_nice = 0; - -static DEFINE_SPINLOCK(ps_spinlock __attribute__((unused))); - -static DECLARE_DELAYED_WORK(ps_tq, ps_tq_int); - -static void ps_set_intr(void (*continuation)(void), - int (*ready)(void), - int timeout, int nice) -{ - unsigned long flags; - - spin_lock_irqsave(&ps_spinlock,flags); - - ps_continuation = continuation; - ps_ready = ready; - ps_timeout = jiffies + timeout; - ps_nice = nice; - - if (!ps_tq_active) { - ps_tq_active = 1; - if (!ps_nice) - schedule_delayed_work(&ps_tq, 0); - else - schedule_delayed_work(&ps_tq, ps_nice-1); - } - spin_unlock_irqrestore(&ps_spinlock,flags); -} - -static void ps_tq_int(struct work_struct *work) -{ - void (*con)(void); - unsigned long flags; - - spin_lock_irqsave(&ps_spinlock,flags); - - con = ps_continuation; - ps_tq_active = 0; - - if (!con) { - spin_unlock_irqrestore(&ps_spinlock,flags); - return; - } - if (!ps_ready || ps_ready() || time_after_eq(jiffies, ps_timeout)) { - ps_continuation = NULL; - spin_unlock_irqrestore(&ps_spinlock,flags); - con(); - return; - } - ps_tq_active = 1; - if (!ps_nice) - schedule_delayed_work(&ps_tq, 0); - else - schedule_delayed_work(&ps_tq, ps_nice-1); - spin_unlock_irqrestore(&ps_spinlock,flags); -} - -/* end of pseudo.h */ - diff --git a/drivers/block/paride/pt.c b/drivers/block/paride/pt.c deleted file mode 100644 index e815312a00ad..000000000000 --- a/drivers/block/paride/pt.c +++ /dev/null @@ -1,1024 +0,0 @@ -/* - pt.c (c) 1998 Grant R. Guenther <grant@torque.net> - Under the terms of the GNU General Public License. - - This is the high-level driver for parallel port ATAPI tape - drives based on chips supported by the paride module. - - The driver implements both rewinding and non-rewinding - devices, filemarks, and the rewind ioctl. It allocates - a small internal "bounce buffer" for each open device, but - otherwise expects buffering and blocking to be done at the - user level. As with most block-structured tapes, short - writes are padded to full tape blocks, so reading back a file - may return more data than was actually written. - - By default, the driver will autoprobe for a single parallel - port ATAPI tape drive, but if their individual parameters are - specified, the driver can handle up to 4 drives. - - The rewinding devices are named /dev/pt0, /dev/pt1, ... - while the non-rewinding devices are /dev/npt0, /dev/npt1, etc. - - The behaviour of the pt driver can be altered by setting - some parameters from the insmod command line. The following - parameters are adjustable: - - drive0 These four arguments can be arrays of - drive1 1-6 integers as follows: - drive2 - drive3 <prt>,<pro>,<uni>,<mod>,<slv>,<dly> - - Where, - - <prt> is the base of the parallel port address for - the corresponding drive. (required) - - <pro> is the protocol number for the adapter that - supports this drive. These numbers are - logged by 'paride' when the protocol modules - are initialised. (0 if not given) - - <uni> for those adapters that support chained - devices, this is the unit selector for the - chain of devices on the given port. It should - be zero for devices that don't support chaining. - (0 if not given) - - <mod> this can be -1 to choose the best mode, or one - of the mode numbers supported by the adapter. - (-1 if not given) - - <slv> ATAPI devices can be jumpered to master or slave. - Set this to 0 to choose the master drive, 1 to - choose the slave, -1 (the default) to choose the - first drive found. - - <dly> some parallel ports require the driver to - go more slowly. -1 sets a default value that - should work with the chosen protocol. Otherwise, - set this to a small integer, the larger it is - the slower the port i/o. In some cases, setting - this to zero will speed up the device. (default -1) - - major You may use this parameter to override the - default major number (96) that this driver - will use. Be sure to change the device - name as well. - - name This parameter is a character string that - contains the name the kernel will use for this - device (in /proc output, for instance). - (default "pt"). - - verbose This parameter controls the amount of logging - that the driver will do. Set it to 0 for - normal operation, 1 to see autoprobe progress - messages, or 2 to see additional debugging - output. (default 0) - - If this driver is built into the kernel, you can use - the following command line parameters, with the same values - as the corresponding module parameters listed above: - - pt.drive0 - pt.drive1 - pt.drive2 - pt.drive3 - - In addition, you can use the parameter pt.disable to disable - the driver entirely. - -*/ - -/* Changes: - - 1.01 GRG 1998.05.06 Round up transfer size, fix ready_wait, - loosed interpretation of ATAPI standard - for clearing error status. - Eliminate sti(); - 1.02 GRG 1998.06.16 Eliminate an Ugh. - 1.03 GRG 1998.08.15 Adjusted PT_TMO, use HZ in loop timing, - extra debugging - 1.04 GRG 1998.09.24 Repair minor coding error, added jumbo support - -*/ - -#define PT_VERSION "1.04" -#define PT_MAJOR 96 -#define PT_NAME "pt" -#define PT_UNITS 4 - -#include <linux/types.h> - -/* Here are things one can override from the insmod command. - Most are autoprobed by paride unless set here. Verbose is on - by default. - -*/ - -static int verbose = 0; -static int major = PT_MAJOR; -static char *name = PT_NAME; -static int disable = 0; - -static int drive0[6] = { 0, 0, 0, -1, -1, -1 }; -static int drive1[6] = { 0, 0, 0, -1, -1, -1 }; -static int drive2[6] = { 0, 0, 0, -1, -1, -1 }; -static int drive3[6] = { 0, 0, 0, -1, -1, -1 }; - -static int (*drives[4])[6] = {&drive0, &drive1, &drive2, &drive3}; - -#define D_PRT 0 -#define D_PRO 1 -#define D_UNI 2 -#define D_MOD 3 -#define D_SLV 4 -#define D_DLY 5 - -#define DU (*drives[unit]) - -/* end of parameters */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/fs.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/mtio.h> -#include <linux/device.h> -#include <linux/sched.h> /* current, TASK_*, schedule_timeout() */ -#include <linux/mutex.h> - -#include <linux/uaccess.h> - -module_param(verbose, int, 0); -module_param(major, int, 0); -module_param(name, charp, 0); -module_param_array(drive0, int, NULL, 0); -module_param_array(drive1, int, NULL, 0); -module_param_array(drive2, int, NULL, 0); -module_param_array(drive3, int, NULL, 0); - -#include "paride.h" - -#define PT_MAX_RETRIES 5 -#define PT_TMO 3000 /* interrupt timeout in jiffies */ -#define PT_SPIN_DEL 50 /* spin delay in micro-seconds */ -#define PT_RESET_TMO 30 /* 30 seconds */ -#define PT_READY_TMO 60 /* 60 seconds */ -#define PT_REWIND_TMO 1200 /* 20 minutes */ - -#define PT_SPIN ((1000000/(HZ*PT_SPIN_DEL))*PT_TMO) - -#define STAT_ERR 0x00001 -#define STAT_INDEX 0x00002 -#define STAT_ECC 0x00004 -#define STAT_DRQ 0x00008 -#define STAT_SEEK 0x00010 -#define STAT_WRERR 0x00020 -#define STAT_READY 0x00040 -#define STAT_BUSY 0x00080 -#define STAT_SENSE 0x1f000 - -#define ATAPI_TEST_READY 0x00 -#define ATAPI_REWIND 0x01 -#define ATAPI_REQ_SENSE 0x03 -#define ATAPI_READ_6 0x08 -#define ATAPI_WRITE_6 0x0a -#define ATAPI_WFM 0x10 -#define ATAPI_IDENTIFY 0x12 -#define ATAPI_MODE_SENSE 0x1a -#define ATAPI_LOG_SENSE 0x4d - -static DEFINE_MUTEX(pt_mutex); -static int pt_open(struct inode *inode, struct file *file); -static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg); -static int pt_release(struct inode *inode, struct file *file); -static ssize_t pt_read(struct file *filp, char __user *buf, - size_t count, loff_t * ppos); -static ssize_t pt_write(struct file *filp, const char __user *buf, - size_t count, loff_t * ppos); -static int pt_detect(void); - -/* bits in tape->flags */ - -#define PT_MEDIA 1 -#define PT_WRITE_OK 2 -#define PT_REWIND 4 -#define PT_WRITING 8 -#define PT_READING 16 -#define PT_EOF 32 - -#define PT_NAMELEN 8 -#define PT_BUFSIZE 16384 - -struct pt_unit { - struct pi_adapter pia; /* interface to paride layer */ - struct pi_adapter *pi; - int flags; /* various state flags */ - int last_sense; /* result of last request sense */ - int drive; /* drive */ - atomic_t available; /* 1 if access is available 0 otherwise */ - int bs; /* block size */ - int capacity; /* Size of tape in KB */ - int present; /* device present ? */ - char *bufptr; - char name[PT_NAMELEN]; /* pf0, pf1, ... */ -}; - -static int pt_identify(struct pt_unit *tape); - -static struct pt_unit pt[PT_UNITS]; - -static char pt_scratch[512]; /* scratch block buffer */ -static void *par_drv; /* reference of parport driver */ - -/* kernel glue structures */ - -static const struct file_operations pt_fops = { - .owner = THIS_MODULE, - .read = pt_read, - .write = pt_write, - .unlocked_ioctl = pt_ioctl, - .open = pt_open, - .release = pt_release, - .llseek = noop_llseek, -}; - -/* sysfs class support */ -static struct class *pt_class; - -static inline int status_reg(struct pi_adapter *pi) -{ - return pi_read_regr(pi, 1, 6); -} - -static inline int read_reg(struct pi_adapter *pi, int reg) -{ - return pi_read_regr(pi, 0, reg); -} - -static inline void write_reg(struct pi_adapter *pi, int reg, int val) -{ - pi_write_regr(pi, 0, reg, val); -} - -static inline u8 DRIVE(struct pt_unit *tape) -{ - return 0xa0+0x10*tape->drive; -} - -static int pt_wait(struct pt_unit *tape, int go, int stop, char *fun, char *msg) -{ - int j, r, e, s, p; - struct pi_adapter *pi = tape->pi; - - j = 0; - while ((((r = status_reg(pi)) & go) || (stop && (!(r & stop)))) - && (j++ < PT_SPIN)) - udelay(PT_SPIN_DEL); - - if ((r & (STAT_ERR & stop)) || (j > PT_SPIN)) { - s = read_reg(pi, 7); - e = read_reg(pi, 1); - p = read_reg(pi, 2); - if (j > PT_SPIN) - e |= 0x100; - if (fun) - printk("%s: %s %s: alt=0x%x stat=0x%x err=0x%x" - " loop=%d phase=%d\n", - tape->name, fun, msg, r, s, e, j, p); - return (e << 8) + s; - } - return 0; -} - -static int pt_command(struct pt_unit *tape, char *cmd, int dlen, char *fun) -{ - struct pi_adapter *pi = tape->pi; - pi_connect(pi); - - write_reg(pi, 6, DRIVE(tape)); - - if (pt_wait(tape, STAT_BUSY | STAT_DRQ, 0, fun, "before command")) { - pi_disconnect(pi); - return -1; - } - - write_reg(pi, 4, dlen % 256); - write_reg(pi, 5, dlen / 256); - write_reg(pi, 7, 0xa0); /* ATAPI packet command */ - - if (pt_wait(tape, STAT_BUSY, STAT_DRQ, fun, "command DRQ")) { - pi_disconnect(pi); - return -1; - } - - if (read_reg(pi, 2) != 1) { - printk("%s: %s: command phase error\n", tape->name, fun); - pi_disconnect(pi); - return -1; - } - - pi_write_block(pi, cmd, 12); - - return 0; -} - -static int pt_completion(struct pt_unit *tape, char *buf, char *fun) -{ - struct pi_adapter *pi = tape->pi; - int r, s, n, p; - - r = pt_wait(tape, STAT_BUSY, STAT_DRQ | STAT_READY | STAT_ERR, - fun, "completion"); - - if (read_reg(pi, 7) & STAT_DRQ) { - n = (((read_reg(pi, 4) + 256 * read_reg(pi, 5)) + - 3) & 0xfffc); - p = read_reg(pi, 2) & 3; - if (p == 0) - pi_write_block(pi, buf, n); - if (p == 2) - pi_read_block(pi, buf, n); - } - - s = pt_wait(tape, STAT_BUSY, STAT_READY | STAT_ERR, fun, "data done"); - - pi_disconnect(pi); - - return (r ? r : s); -} - -static void pt_req_sense(struct pt_unit *tape, int quiet) -{ - char rs_cmd[12] = { ATAPI_REQ_SENSE, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0 }; - char buf[16]; - int r; - - r = pt_command(tape, rs_cmd, 16, "Request sense"); - mdelay(1); - if (!r) - pt_completion(tape, buf, "Request sense"); - - tape->last_sense = -1; - if (!r) { - if (!quiet) - printk("%s: Sense key: %x, ASC: %x, ASQ: %x\n", - tape->name, buf[2] & 0xf, buf[12], buf[13]); - tape->last_sense = (buf[2] & 0xf) | ((buf[12] & 0xff) << 8) - | ((buf[13] & 0xff) << 16); - } -} - -static int pt_atapi(struct pt_unit *tape, char *cmd, int dlen, char *buf, char *fun) -{ - int r; - - r = pt_command(tape, cmd, dlen, fun); - mdelay(1); - if (!r) - r = pt_completion(tape, buf, fun); - if (r) - pt_req_sense(tape, !fun); - - return r; -} - -static void pt_sleep(int cs) -{ - schedule_timeout_interruptible(cs); -} - -static int pt_poll_dsc(struct pt_unit *tape, int pause, int tmo, char *msg) -{ - struct pi_adapter *pi = tape->pi; - int k, e, s; - - k = 0; - e = 0; - s = 0; - while (k < tmo) { - pt_sleep(pause); - k++; - pi_connect(pi); - write_reg(pi, 6, DRIVE(tape)); - s = read_reg(pi, 7); - e = read_reg(pi, 1); - pi_disconnect(pi); - if (s & (STAT_ERR | STAT_SEEK)) - break; - } - if ((k >= tmo) || (s & STAT_ERR)) { - if (k >= tmo) - printk("%s: %s DSC timeout\n", tape->name, msg); - else - printk("%s: %s stat=0x%x err=0x%x\n", tape->name, msg, s, - e); - pt_req_sense(tape, 0); - return 0; - } - return 1; -} - -static void pt_media_access_cmd(struct pt_unit *tape, int tmo, char *cmd, char *fun) -{ - if (pt_command(tape, cmd, 0, fun)) { - pt_req_sense(tape, 0); - return; - } - pi_disconnect(tape->pi); - pt_poll_dsc(tape, HZ, tmo, fun); -} - -static void pt_rewind(struct pt_unit *tape) -{ - char rw_cmd[12] = { ATAPI_REWIND, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - - pt_media_access_cmd(tape, PT_REWIND_TMO, rw_cmd, "rewind"); -} - -static void pt_write_fm(struct pt_unit *tape) -{ - char wm_cmd[12] = { ATAPI_WFM, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }; - - pt_media_access_cmd(tape, PT_TMO, wm_cmd, "write filemark"); -} - -#define DBMSG(msg) ((verbose>1)?(msg):NULL) - -static int pt_reset(struct pt_unit *tape) -{ - struct pi_adapter *pi = tape->pi; - int i, k, flg; - int expect[5] = { 1, 1, 1, 0x14, 0xeb }; - - pi_connect(pi); - write_reg(pi, 6, DRIVE(tape)); - write_reg(pi, 7, 8); - - pt_sleep(20 * HZ / 1000); - - k = 0; - while ((k++ < PT_RESET_TMO) && (status_reg(pi) & STAT_BUSY)) - pt_sleep(HZ / 10); - - flg = 1; - for (i = 0; i < 5; i++) - flg &= (read_reg(pi, i + 1) == expect[i]); - - if (verbose) { - printk("%s: Reset (%d) signature = ", tape->name, k); - for (i = 0; i < 5; i++) - printk("%3x", read_reg(pi, i + 1)); - if (!flg) - printk(" (incorrect)"); - printk("\n"); - } - - pi_disconnect(pi); - return flg - 1; -} - -static int pt_ready_wait(struct pt_unit *tape, int tmo) -{ - char tr_cmd[12] = { ATAPI_TEST_READY, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int k, p; - - k = 0; - while (k < tmo) { - tape->last_sense = 0; - pt_atapi(tape, tr_cmd, 0, NULL, DBMSG("test unit ready")); - p = tape->last_sense; - if (!p) - return 0; - if (!(((p & 0xffff) == 0x0402) || ((p & 0xff) == 6))) - return p; - k++; - pt_sleep(HZ); - } - return 0x000020; /* timeout */ -} - -static void xs(char *buf, char *targ, int offs, int len) -{ - int j, k, l; - - j = 0; - l = 0; - for (k = 0; k < len; k++) - if ((buf[k + offs] != 0x20) || (buf[k + offs] != l)) - l = targ[j++] = buf[k + offs]; - if (l == 0x20) - j--; - targ[j] = 0; -} - -static int xn(char *buf, int offs, int size) -{ - int v, k; - - v = 0; - for (k = 0; k < size; k++) - v = v * 256 + (buf[k + offs] & 0xff); - return v; -} - -static int pt_identify(struct pt_unit *tape) -{ - int dt, s; - char *ms[2] = { "master", "slave" }; - char mf[10], id[18]; - char id_cmd[12] = { ATAPI_IDENTIFY, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0 }; - char ms_cmd[12] = - { ATAPI_MODE_SENSE, 0, 0x2a, 0, 36, 0, 0, 0, 0, 0, 0, 0 }; - char ls_cmd[12] = - { ATAPI_LOG_SENSE, 0, 0x71, 0, 0, 0, 0, 0, 36, 0, 0, 0 }; - char buf[36]; - - s = pt_atapi(tape, id_cmd, 36, buf, "identify"); - if (s) - return -1; - - dt = buf[0] & 0x1f; - if (dt != 1) { - if (verbose) - printk("%s: Drive %d, unsupported type %d\n", - tape->name, tape->drive, dt); - return -1; - } - - xs(buf, mf, 8, 8); - xs(buf, id, 16, 16); - - tape->flags = 0; - tape->capacity = 0; - tape->bs = 0; - - if (!pt_ready_wait(tape, PT_READY_TMO)) - tape->flags |= PT_MEDIA; - - if (!pt_atapi(tape, ms_cmd, 36, buf, "mode sense")) { - if (!(buf[2] & 0x80)) - tape->flags |= PT_WRITE_OK; - tape->bs = xn(buf, 10, 2); - } - - if (!pt_atapi(tape, ls_cmd, 36, buf, "log sense")) - tape->capacity = xn(buf, 24, 4); - - printk("%s: %s %s, %s", tape->name, mf, id, ms[tape->drive]); - if (!(tape->flags & PT_MEDIA)) - printk(", no media\n"); - else { - if (!(tape->flags & PT_WRITE_OK)) - printk(", RO"); - printk(", blocksize %d, %d MB\n", tape->bs, tape->capacity / 1024); - } - - return 0; -} - - -/* - * returns 0, with id set if drive is detected - * -1, if drive detection failed - */ -static int pt_probe(struct pt_unit *tape) -{ - if (tape->drive == -1) { - for (tape->drive = 0; tape->drive <= 1; tape->drive++) - if (!pt_reset(tape)) - return pt_identify(tape); - } else { - if (!pt_reset(tape)) - return pt_identify(tape); - } - return -1; -} - -static int pt_detect(void) -{ - struct pt_unit *tape; - int specified = 0, found = 0; - int unit; - - printk("%s: %s version %s, major %d\n", name, name, PT_VERSION, major); - - par_drv = pi_register_driver(name); - if (!par_drv) { - pr_err("failed to register %s driver\n", name); - return -1; - } - - specified = 0; - for (unit = 0; unit < PT_UNITS; unit++) { - struct pt_unit *tape = &pt[unit]; - tape->pi = &tape->pia; - atomic_set(&tape->available, 1); - tape->flags = 0; - tape->last_sense = 0; - tape->present = 0; - tape->bufptr = NULL; - tape->drive = DU[D_SLV]; - snprintf(tape->name, PT_NAMELEN, "%s%d", name, unit); - if (!DU[D_PRT]) - continue; - specified++; - if (pi_init(tape->pi, 0, DU[D_PRT], DU[D_MOD], DU[D_UNI], - DU[D_PRO], DU[D_DLY], pt_scratch, PI_PT, - verbose, tape->name)) { - if (!pt_probe(tape)) { - tape->present = 1; - found++; - } else - pi_release(tape->pi); - } - } - if (specified == 0) { - tape = pt; - if (pi_init(tape->pi, 1, -1, -1, -1, -1, -1, pt_scratch, - PI_PT, verbose, tape->name)) { - if (!pt_probe(tape)) { - tape->present = 1; - found++; - } else - pi_release(tape->pi); - } - - } - if (found) - return 0; - - pi_unregister_driver(par_drv); - printk("%s: No ATAPI tape drive detected\n", name); - return -1; -} - -static int pt_open(struct inode *inode, struct file *file) -{ - int unit = iminor(inode) & 0x7F; - struct pt_unit *tape = pt + unit; - int err; - - mutex_lock(&pt_mutex); - if (unit >= PT_UNITS || (!tape->present)) { - mutex_unlock(&pt_mutex); - return -ENODEV; - } - - err = -EBUSY; - if (!atomic_dec_and_test(&tape->available)) - goto out; - - pt_identify(tape); - - err = -ENODEV; - if (!(tape->flags & PT_MEDIA)) - goto out; - - err = -EROFS; - if ((!(tape->flags & PT_WRITE_OK)) && (file->f_mode & FMODE_WRITE)) - goto out; - - if (!(iminor(inode) & 128)) - tape->flags |= PT_REWIND; - - err = -ENOMEM; - tape->bufptr = kmalloc(PT_BUFSIZE, GFP_KERNEL); - if (tape->bufptr == NULL) { - printk("%s: buffer allocation failed\n", tape->name); - goto out; - } - - file->private_data = tape; - mutex_unlock(&pt_mutex); - return 0; - -out: - atomic_inc(&tape->available); - mutex_unlock(&pt_mutex); - return err; -} - -static long pt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct pt_unit *tape = file->private_data; - struct mtop __user *p = (void __user *)arg; - struct mtop mtop; - - switch (cmd) { - case MTIOCTOP: - if (copy_from_user(&mtop, p, sizeof(struct mtop))) - return -EFAULT; - - switch (mtop.mt_op) { - - case MTREW: - mutex_lock(&pt_mutex); - pt_rewind(tape); - mutex_unlock(&pt_mutex); - return 0; - - case MTWEOF: - mutex_lock(&pt_mutex); - pt_write_fm(tape); - mutex_unlock(&pt_mutex); - return 0; - - default: - /* FIXME: rate limit ?? */ - printk(KERN_DEBUG "%s: Unimplemented mt_op %d\n", tape->name, - mtop.mt_op); - return -EINVAL; - } - - default: - return -ENOTTY; - } -} - -static int -pt_release(struct inode *inode, struct file *file) -{ - struct pt_unit *tape = file->private_data; - - if (atomic_read(&tape->available) > 1) - return -EINVAL; - - if (tape->flags & PT_WRITING) - pt_write_fm(tape); - - if (tape->flags & PT_REWIND) - pt_rewind(tape); - - kfree(tape->bufptr); - tape->bufptr = NULL; - - atomic_inc(&tape->available); - - return 0; - -} - -static ssize_t pt_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) -{ - struct pt_unit *tape = filp->private_data; - struct pi_adapter *pi = tape->pi; - char rd_cmd[12] = { ATAPI_READ_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int k, n, r, p, s, t, b; - - if (!(tape->flags & (PT_READING | PT_WRITING))) { - tape->flags |= PT_READING; - if (pt_atapi(tape, rd_cmd, 0, NULL, "start read-ahead")) - return -EIO; - } else if (tape->flags & PT_WRITING) - return -EIO; - - if (tape->flags & PT_EOF) - return 0; - - t = 0; - - while (count > 0) { - - if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "read")) - return -EIO; - - n = count; - if (n > 32768) - n = 32768; /* max per command */ - b = (n - 1 + tape->bs) / tape->bs; - n = b * tape->bs; /* rounded up to even block */ - - rd_cmd[4] = b; - - r = pt_command(tape, rd_cmd, n, "read"); - - mdelay(1); - - if (r) { - pt_req_sense(tape, 0); - return -EIO; - } - - while (1) { - - r = pt_wait(tape, STAT_BUSY, - STAT_DRQ | STAT_ERR | STAT_READY, - DBMSG("read DRQ"), ""); - - if (r & STAT_SENSE) { - pi_disconnect(pi); - pt_req_sense(tape, 0); - return -EIO; - } - - if (r) - tape->flags |= PT_EOF; - - s = read_reg(pi, 7); - - if (!(s & STAT_DRQ)) - break; - - n = (read_reg(pi, 4) + 256 * read_reg(pi, 5)); - p = (read_reg(pi, 2) & 3); - if (p != 2) { - pi_disconnect(pi); - printk("%s: Phase error on read: %d\n", tape->name, - p); - return -EIO; - } - - while (n > 0) { - k = n; - if (k > PT_BUFSIZE) - k = PT_BUFSIZE; - pi_read_block(pi, tape->bufptr, k); - n -= k; - b = k; - if (b > count) - b = count; - if (copy_to_user(buf + t, tape->bufptr, b)) { - pi_disconnect(pi); - return -EFAULT; - } - t += b; - count -= b; - } - - } - pi_disconnect(pi); - if (tape->flags & PT_EOF) - break; - } - - return t; - -} - -static ssize_t pt_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) -{ - struct pt_unit *tape = filp->private_data; - struct pi_adapter *pi = tape->pi; - char wr_cmd[12] = { ATAPI_WRITE_6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - int k, n, r, p, s, t, b; - - if (!(tape->flags & PT_WRITE_OK)) - return -EROFS; - - if (!(tape->flags & (PT_READING | PT_WRITING))) { - tape->flags |= PT_WRITING; - if (pt_atapi - (tape, wr_cmd, 0, NULL, "start buffer-available mode")) - return -EIO; - } else if (tape->flags & PT_READING) - return -EIO; - - if (tape->flags & PT_EOF) - return -ENOSPC; - - t = 0; - - while (count > 0) { - - if (!pt_poll_dsc(tape, HZ / 100, PT_TMO, "write")) - return -EIO; - - n = count; - if (n > 32768) - n = 32768; /* max per command */ - b = (n - 1 + tape->bs) / tape->bs; - n = b * tape->bs; /* rounded up to even block */ - - wr_cmd[4] = b; - - r = pt_command(tape, wr_cmd, n, "write"); - - mdelay(1); - - if (r) { /* error delivering command only */ - pt_req_sense(tape, 0); - return -EIO; - } - - while (1) { - - r = pt_wait(tape, STAT_BUSY, - STAT_DRQ | STAT_ERR | STAT_READY, - DBMSG("write DRQ"), NULL); - - if (r & STAT_SENSE) { - pi_disconnect(pi); - pt_req_sense(tape, 0); - return -EIO; - } - - if (r) - tape->flags |= PT_EOF; - - s = read_reg(pi, 7); - - if (!(s & STAT_DRQ)) - break; - - n = (read_reg(pi, 4) + 256 * read_reg(pi, 5)); - p = (read_reg(pi, 2) & 3); - if (p != 0) { - pi_disconnect(pi); - printk("%s: Phase error on write: %d \n", - tape->name, p); - return -EIO; - } - - while (n > 0) { - k = n; - if (k > PT_BUFSIZE) - k = PT_BUFSIZE; - b = k; - if (b > count) - b = count; - if (copy_from_user(tape->bufptr, buf + t, b)) { - pi_disconnect(pi); - return -EFAULT; - } - pi_write_block(pi, tape->bufptr, k); - t += b; - count -= b; - n -= k; - } - - } - pi_disconnect(pi); - if (tape->flags & PT_EOF) - break; - } - - return t; -} - -static int __init pt_init(void) -{ - int unit; - int err; - - if (disable) { - err = -EINVAL; - goto out; - } - - if (pt_detect()) { - err = -ENODEV; - goto out; - } - - err = register_chrdev(major, name, &pt_fops); - if (err < 0) { - printk("pt_init: unable to get major number %d\n", major); - for (unit = 0; unit < PT_UNITS; unit++) - if (pt[unit].present) - pi_release(pt[unit].pi); - goto out; - } - major = err; - pt_class = class_create(THIS_MODULE, "pt"); - if (IS_ERR(pt_class)) { - err = PTR_ERR(pt_class); - goto out_chrdev; - } - - for (unit = 0; unit < PT_UNITS; unit++) - if (pt[unit].present) { - device_create(pt_class, NULL, MKDEV(major, unit), NULL, - "pt%d", unit); - device_create(pt_class, NULL, MKDEV(major, unit + 128), - NULL, "pt%dn", unit); - } - goto out; - -out_chrdev: - unregister_chrdev(major, "pt"); -out: - return err; -} - -static void __exit pt_exit(void) -{ - int unit; - for (unit = 0; unit < PT_UNITS; unit++) - if (pt[unit].present) { - device_destroy(pt_class, MKDEV(major, unit)); - device_destroy(pt_class, MKDEV(major, unit + 128)); - } - class_destroy(pt_class); - unregister_chrdev(major, name); - for (unit = 0; unit < PT_UNITS; unit++) - if (pt[unit].present) - pi_release(pt[unit].pi); -} - -MODULE_LICENSE("GPL"); -module_init(pt_init) -module_exit(pt_exit) diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c index 2022ffb45041..1c8040d250ea 100644 --- a/drivers/scsi/ipr.c +++ b/drivers/scsi/ipr.c @@ -5370,9 +5370,9 @@ static int __ipr_eh_dev_reset(struct scsi_cmnd *scsi_cmd) continue; ipr_cmd->done = ipr_sata_eh_done; - if (!(ipr_cmd->qc->flags & ATA_QCFLAG_FAILED)) { + if (!(ipr_cmd->qc->flags & ATA_QCFLAG_EH)) { ipr_cmd->qc->err_mask |= AC_ERR_TIMEOUT; - ipr_cmd->qc->flags |= ATA_QCFLAG_FAILED; + ipr_cmd->qc->flags |= ATA_QCFLAG_EH; } } } @@ -7142,11 +7142,8 @@ static unsigned int ipr_qc_issue(struct ata_queued_cmd *qc) /** * ipr_qc_fill_rtf - Read result TF * @qc: ATA queued command - * - * Return value: - * true **/ -static bool ipr_qc_fill_rtf(struct ata_queued_cmd *qc) +static void ipr_qc_fill_rtf(struct ata_queued_cmd *qc) { struct ipr_sata_port *sata_port = qc->ap->private_data; struct ipr_ioasa_gata *g = &sata_port->ioasa; @@ -7163,8 +7160,6 @@ static bool ipr_qc_fill_rtf(struct ata_queued_cmd *qc) tf->hob_lbal = g->hob_lbal; tf->hob_lbam = g->hob_lbam; tf->hob_lbah = g->hob_lbah; - - return true; } static struct ata_port_operations ipr_sata_ops = { diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 5e80225b5308..12d9bdd11a4c 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -125,7 +125,7 @@ static void sas_ata_task_done(struct sas_task *task) } else { link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.fis[2]); if (unlikely(link->eh_info.err_mask)) - qc->flags |= ATA_QCFLAG_FAILED; + qc->flags |= ATA_QCFLAG_EH; } } else { ac = sas_to_ata_err(stat); @@ -136,7 +136,7 @@ static void sas_ata_task_done(struct sas_task *task) qc->err_mask = ac; } else { link->eh_info.err_mask |= AC_ERR_DEV; - qc->flags |= ATA_QCFLAG_FAILED; + qc->flags |= ATA_QCFLAG_EH; } dev->sata_dev.fis[2] = ATA_ERR | ATA_DRDY; /* tf status */ @@ -226,12 +226,11 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) return ret; } -static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc) +static void sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc) { struct domain_device *dev = qc->ap->private_data; ata_tf_from_fis(dev->sata_dev.fis, &qc->result_tf); - return true; } static struct sas_internal *dev_to_sas_internal(struct domain_device *dev) @@ -476,7 +475,7 @@ static void sas_ata_internal_abort(struct sas_task *task) static void sas_ata_post_internal(struct ata_queued_cmd *qc) { - if (qc->flags & ATA_QCFLAG_FAILED) + if (qc->flags & ATA_QCFLAG_EH) qc->err_mask |= AC_ERR_OTHER; if (qc->err_mask) { @@ -631,7 +630,7 @@ void sas_ata_task_abort(struct sas_task *task) /* Internal command, fake a timeout and complete. */ qc->flags &= ~ATA_QCFLAG_ACTIVE; - qc->flags |= ATA_QCFLAG_FAILED; + qc->flags |= ATA_QCFLAG_EH; qc->err_mask |= AC_ERR_TIMEOUT; waiting = qc->private_data; complete(waiting); |