ata changes for 6.5-rc1
- Add support for the .remove_new callback to the ata_platform code to simplify device removal interface (Uwe). - Code simplification in ata_dev_revalidate() (Yahu) - Fix code indentation and coding style in the pata_parport protocol modules to avoid warnings from static code analyzers (me) - Clarify ata_eh_qc_retry() behavior with better comments (Niklas) - Simplify and improve ata_change_queue_depth() behavior to have a consistent behavior between libsas managed devices and libata managed devices (e.g. AHCI connected devices) (me). - Cleanup libata-scsi and libata-eh code to use the ata_ncq_enabled() and ata_ncq_supported() helpers instead of open coding flags tests (me) - Cleanup ahci_reset_controller() code (me). - Change the pata_octeon_cf and sata_svw drivers to use of_property_read_reg() to simplify the code (Rob, me). - Remove unnecessary include files from ahci_octeon driver (me) - Modify the DesignWare ahci dt bindings to add support for the Rockchip RK3588 AHCI (Sebastian). -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQSRPv8tYSvhwAzJdzjdoc3SxdoYdgUCZJourwAKCRDdoc3SxdoY dv43AQDzAFY0/0sjvqltGC31wRzzh/vEQFWsYt89Q4csMr4QgAEAkLO1gquH5/Wt sxnCLh1WdFqbyNy6xsw+CXrfeREGDgo= =IzEr -----END PGP SIGNATURE----- Merge tag 'ata-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/libata Pull ata updates from Damien Le Moal: - Add support for the .remove_new callback to the ata_platform code to simplify device removal interface (Uwe) - Code simplification in ata_dev_revalidate() (Yahu) - Fix code indentation and coding style in the pata_parport protocol modules to avoid warnings from static code analyzers (me) - Clarify ata_eh_qc_retry() behavior with better comments (Niklas) - Simplify and improve ata_change_queue_depth() behavior to have a consistent behavior between libsas managed devices and libata managed devices (e.g. AHCI connected devices) (me) - Cleanup libata-scsi and libata-eh code to use the ata_ncq_enabled() and ata_ncq_supported() helpers instead of open coding flags tests (me) - Cleanup ahci_reset_controller() code (me) - Change the pata_octeon_cf and sata_svw drivers to use of_property_read_reg() to simplify the code (Rob, me) - Remove unnecessary include files from ahci_octeon driver (me) - Modify the DesignWare ahci dt bindings to add support for the Rockchip RK3588 AHCI (Sebastian) * tag 'ata-6.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/dlemoal/libata: (29 commits) dt-bindings: phy: rockchip: rk3588 has two reset lines dt-bindings: ata: dwc-ahci: add Rockchip RK3588 dt-bindings: ata: dwc-ahci: add PHY clocks ata: ahci_octeon: Remove unnecessary include ata: pata_octeon_cf: Add missing header include ata: ahci: Cleanup ahci_reset_controller() ata: Use of_property_read_reg() to parse "reg" ata: libata-scsi: Use ata_ncq_supported in ata_scsi_dev_config() ata: libata-eh: Use ata_ncq_enabled() in ata_eh_speed_down() ata: libata-sata: Improve ata_change_queue_depth() ata: libata-sata: Simplify ata_change_queue_depth() ata: libata-eh: Clarify ata_eh_qc_retry() behavior at call site ata: pata_parport: Fix on26 module code indentation and style ata: pata_parport: Fix on20 module code indentation and style ata: pata_parport: Fix ktti module code indentation and style ata: pata_parport: Fix kbic module code indentation and style ata: pata_parport: Fix friq module code indentation and style ata: pata_parport: Fix fit3 module code indentation and style ata: pata_parport: Fix fit2 module code indentation and style ata: pata_parport: Fix epia module code indentation and style ...
This commit is contained in:
Коммит
1546cd4bfd
|
@ -0,0 +1,124 @@
|
|||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/ata/rockchip,dwc-ahci.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Synopsys DWC AHCI SATA controller for Rockchip devices
|
||||
|
||||
maintainers:
|
||||
- Serge Semin <fancer.lancer@gmail.com>
|
||||
|
||||
description:
|
||||
This document defines device tree bindings for the Synopsys DWC
|
||||
implementation of the AHCI SATA controller found in Rockchip
|
||||
devices.
|
||||
|
||||
select:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- rockchip,rk3568-dwc-ahci
|
||||
- rockchip,rk3588-dwc-ahci
|
||||
required:
|
||||
- compatible
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- rockchip,rk3568-dwc-ahci
|
||||
- rockchip,rk3588-dwc-ahci
|
||||
- const: snps,dwc-ahci
|
||||
|
||||
ports-implemented:
|
||||
const: 1
|
||||
|
||||
sata-port@0:
|
||||
$ref: /schemas/ata/snps,dwc-ahci-common.yaml#/$defs/dwc-ahci-port
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 0
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
patternProperties:
|
||||
"^sata-port@[1-9a-e]$": false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
- ports-implemented
|
||||
|
||||
allOf:
|
||||
- $ref: snps,dwc-ahci-common.yaml#
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- rockchip,rk3588-dwc-ahci
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 5
|
||||
clock-names:
|
||||
items:
|
||||
- const: sata
|
||||
- const: pmalive
|
||||
- const: rxoob
|
||||
- const: ref
|
||||
- const: asic
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
enum:
|
||||
- rockchip,rk3568-dwc-ahci
|
||||
then:
|
||||
properties:
|
||||
clocks:
|
||||
maxItems: 3
|
||||
clock-names:
|
||||
items:
|
||||
- const: sata
|
||||
- const: pmalive
|
||||
- const: rxoob
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/rockchip,rk3588-cru.h>
|
||||
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||
#include <dt-bindings/ata/ahci.h>
|
||||
#include <dt-bindings/phy/phy.h>
|
||||
|
||||
sata@fe210000 {
|
||||
compatible = "rockchip,rk3588-dwc-ahci", "snps,dwc-ahci";
|
||||
reg = <0xfe210000 0x1000>;
|
||||
clocks = <&cru ACLK_SATA0>, <&cru CLK_PMALIVE0>,
|
||||
<&cru CLK_RXOOB0>, <&cru CLK_PIPEPHY0_REF>,
|
||||
<&cru CLK_PIPEPHY0_PIPE_ASIC_G>;
|
||||
clock-names = "sata", "pmalive", "rxoob", "ref", "asic";
|
||||
interrupts = <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH 0>;
|
||||
ports-implemented = <0x1>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sata-port@0 {
|
||||
reg = <0>;
|
||||
hba-port-cap = <HBA_PORT_FBSCP>;
|
||||
phys = <&combphy0_ps PHY_TYPE_SATA>;
|
||||
phy-names = "sata-phy";
|
||||
snps,rx-ts-max = <32>;
|
||||
snps,tx-ts-max = <32>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -31,11 +31,11 @@ properties:
|
|||
PM-alive clock, RxOOB detection clock, embedded PHYs reference (Rx/Tx)
|
||||
clock, etc.
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
maxItems: 6
|
||||
|
||||
clock-names:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
maxItems: 6
|
||||
items:
|
||||
oneOf:
|
||||
- description: Application APB/AHB/AXI BIU clock
|
||||
|
@ -48,6 +48,10 @@ properties:
|
|||
const: pmalive
|
||||
- description: RxOOB detection clock
|
||||
const: rxoob
|
||||
- description: PHY Transmit Clock
|
||||
const: asic
|
||||
- description: PHY Receive Clock
|
||||
const: rbc
|
||||
- description: SATA Ports reference clock
|
||||
const: ref
|
||||
|
||||
|
|
|
@ -13,6 +13,15 @@ description:
|
|||
This document defines device tree bindings for the generic Synopsys DWC
|
||||
implementation of the AHCI SATA controller.
|
||||
|
||||
select:
|
||||
properties:
|
||||
compatible:
|
||||
enum:
|
||||
- snps,dwc-ahci
|
||||
- snps,spear-ahci
|
||||
required:
|
||||
- compatible
|
||||
|
||||
allOf:
|
||||
- $ref: snps,dwc-ahci-common.yaml#
|
||||
|
||||
|
@ -23,10 +32,6 @@ properties:
|
|||
const: snps,dwc-ahci
|
||||
- description: SPEAr1340 AHCI SATA device
|
||||
const: snps,spear-ahci
|
||||
- description: Rockhip RK3568 AHCI controller
|
||||
items:
|
||||
- const: rockchip,rk3568-dwc-ahci
|
||||
- const: snps,dwc-ahci
|
||||
|
||||
patternProperties:
|
||||
"^sata-port@[0-9a-e]$":
|
||||
|
|
|
@ -31,8 +31,14 @@ properties:
|
|||
- const: pipe
|
||||
|
||||
resets:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
reset-names:
|
||||
minItems: 1
|
||||
items:
|
||||
- description: exclusive PHY reset line
|
||||
- const: phy
|
||||
- const: apb
|
||||
|
||||
rockchip,enable-ssc:
|
||||
type: boolean
|
||||
|
@ -78,6 +84,32 @@ required:
|
|||
- rockchip,pipe-phy-grf
|
||||
- "#phy-cells"
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: rockchip,rk3568-naneng-combphy
|
||||
then:
|
||||
properties:
|
||||
resets:
|
||||
maxItems: 1
|
||||
reset-names:
|
||||
maxItems: 1
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
contains:
|
||||
const: rockchip,rk3588-naneng-combphy
|
||||
then:
|
||||
properties:
|
||||
resets:
|
||||
minItems: 2
|
||||
reset-names:
|
||||
minItems: 2
|
||||
required:
|
||||
- reset-names
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
|
|
|
@ -544,7 +544,7 @@ out_reset:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int brcm_ahci_remove(struct platform_device *pdev)
|
||||
static void brcm_ahci_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct ata_host *host = dev_get_drvdata(&pdev->dev);
|
||||
struct ahci_host_priv *hpriv = host->private_data;
|
||||
|
@ -552,7 +552,7 @@ static int brcm_ahci_remove(struct platform_device *pdev)
|
|||
|
||||
brcm_sata_phys_disable(priv);
|
||||
|
||||
return ata_platform_remove_one(pdev);
|
||||
ata_platform_remove_one(pdev);
|
||||
}
|
||||
|
||||
static void brcm_ahci_shutdown(struct platform_device *pdev)
|
||||
|
@ -573,7 +573,7 @@ static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume);
|
|||
|
||||
static struct platform_driver brcm_ahci_driver = {
|
||||
.probe = brcm_ahci_probe,
|
||||
.remove = brcm_ahci_remove,
|
||||
.remove_new = brcm_ahci_remove,
|
||||
.shutdown = brcm_ahci_shutdown,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
|
|
|
@ -369,7 +369,7 @@ MODULE_DEVICE_TABLE(of, ceva_ahci_of_match);
|
|||
|
||||
static struct platform_driver ceva_ahci_driver = {
|
||||
.probe = ceva_ahci_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = ceva_ahci_of_match,
|
||||
|
|
|
@ -238,7 +238,7 @@ MODULE_DEVICE_TABLE(of, ahci_da850_of_match);
|
|||
|
||||
static struct platform_driver ahci_da850_driver = {
|
||||
.probe = ahci_da850_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = ahci_da850_of_match,
|
||||
|
|
|
@ -182,7 +182,7 @@ MODULE_DEVICE_TABLE(of, ahci_dm816_of_match);
|
|||
|
||||
static struct platform_driver ahci_dm816_driver = {
|
||||
.probe = ahci_dm816_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.driver = {
|
||||
.name = AHCI_DM816_DRV_NAME,
|
||||
.of_match_table = ahci_dm816_of_match,
|
||||
|
|
|
@ -478,7 +478,7 @@ MODULE_DEVICE_TABLE(of, ahci_dwc_of_match);
|
|||
|
||||
static struct platform_driver ahci_dwc_driver = {
|
||||
.probe = ahci_dwc_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.shutdown = ahci_platform_shutdown,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
|
|
|
@ -1223,7 +1223,7 @@ static SIMPLE_DEV_PM_OPS(ahci_imx_pm_ops, imx_ahci_suspend, imx_ahci_resume);
|
|||
|
||||
static struct platform_driver imx_ahci_driver = {
|
||||
.probe = imx_ahci_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = imx_ahci_of_match,
|
||||
|
|
|
@ -173,7 +173,7 @@ MODULE_DEVICE_TABLE(of, ahci_of_match);
|
|||
|
||||
static struct platform_driver mtk_ahci_driver = {
|
||||
.probe = mtk_ahci_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = ahci_of_match,
|
||||
|
|
|
@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(of, ahci_mvebu_of_match);
|
|||
|
||||
static struct platform_driver ahci_mvebu_driver = {
|
||||
.probe = ahci_mvebu_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.suspend = ahci_mvebu_suspend,
|
||||
.resume = ahci_mvebu_resume,
|
||||
.driver = {
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include <linux/of_platform.h>
|
||||
|
||||
#include <asm/octeon/octeon.h>
|
||||
#include <asm/bitfield.h>
|
||||
|
||||
#define CVMX_SATA_UCTL_SHIM_CFG 0xE8
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ MODULE_DEVICE_TABLE(acpi, ahci_acpi_match);
|
|||
|
||||
static struct platform_driver ahci_driver = {
|
||||
.probe = ahci_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.shutdown = ahci_platform_shutdown,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
|
|
|
@ -359,7 +359,7 @@ static SIMPLE_DEV_PM_OPS(ahci_qoriq_pm_ops, ahci_platform_suspend,
|
|||
|
||||
static struct platform_driver ahci_qoriq_driver = {
|
||||
.probe = ahci_qoriq_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = ahci_qoriq_of_match,
|
||||
|
|
|
@ -187,7 +187,7 @@ MODULE_DEVICE_TABLE(acpi, ahci_acpi_match);
|
|||
|
||||
static struct platform_driver ahci_seattle_driver = {
|
||||
.probe = ahci_seattle_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.acpi_match_table = ahci_acpi_match,
|
||||
|
|
|
@ -239,7 +239,7 @@ static struct platform_driver st_ahci_driver = {
|
|||
.of_match_table = st_ahci_match,
|
||||
},
|
||||
.probe = st_ahci_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
};
|
||||
module_platform_driver(st_ahci_driver);
|
||||
|
||||
|
|
|
@ -292,7 +292,7 @@ MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match);
|
|||
|
||||
static struct platform_driver ahci_sunxi_driver = {
|
||||
.probe = ahci_sunxi_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = ahci_sunxi_of_match,
|
||||
|
|
|
@ -609,7 +609,7 @@ deinit_controller:
|
|||
|
||||
static struct platform_driver tegra_ahci_driver = {
|
||||
.probe = tegra_ahci_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = tegra_ahci_of_match,
|
||||
|
|
|
@ -868,7 +868,7 @@ disable_resources:
|
|||
|
||||
static struct platform_driver xgene_ahci_driver = {
|
||||
.probe = xgene_ahci_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
.of_match_table = xgene_ahci_of_match,
|
||||
|
|
|
@ -975,44 +975,43 @@ int ahci_reset_controller(struct ata_host *host)
|
|||
void __iomem *mmio = hpriv->mmio;
|
||||
u32 tmp;
|
||||
|
||||
/* we must be in AHCI mode, before using anything
|
||||
* AHCI-specific, such as HOST_RESET.
|
||||
/*
|
||||
* We must be in AHCI mode, before using anything AHCI-specific, such
|
||||
* as HOST_RESET.
|
||||
*/
|
||||
ahci_enable_ahci(mmio);
|
||||
|
||||
/* global controller reset */
|
||||
if (!ahci_skip_host_reset) {
|
||||
tmp = readl(mmio + HOST_CTL);
|
||||
if ((tmp & HOST_RESET) == 0) {
|
||||
writel(tmp | HOST_RESET, mmio + HOST_CTL);
|
||||
readl(mmio + HOST_CTL); /* flush */
|
||||
}
|
||||
/* Global controller reset */
|
||||
if (ahci_skip_host_reset) {
|
||||
dev_info(host->dev, "Skipping global host reset\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* to perform host reset, OS should set HOST_RESET
|
||||
* and poll until this bit is read to be "0".
|
||||
* reset must complete within 1 second, or
|
||||
* the hardware should be considered fried.
|
||||
*/
|
||||
tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET,
|
||||
HOST_RESET, 10, 1000);
|
||||
tmp = readl(mmio + HOST_CTL);
|
||||
if (!(tmp & HOST_RESET)) {
|
||||
writel(tmp | HOST_RESET, mmio + HOST_CTL);
|
||||
readl(mmio + HOST_CTL); /* flush */
|
||||
}
|
||||
|
||||
if (tmp & HOST_RESET) {
|
||||
dev_err(host->dev, "controller reset failed (0x%x)\n",
|
||||
tmp);
|
||||
return -EIO;
|
||||
}
|
||||
/*
|
||||
* To perform host reset, OS should set HOST_RESET and poll until this
|
||||
* bit is read to be "0". Reset must complete within 1 second, or the
|
||||
* hardware should be considered fried.
|
||||
*/
|
||||
tmp = ata_wait_register(NULL, mmio + HOST_CTL, HOST_RESET,
|
||||
HOST_RESET, 10, 1000);
|
||||
if (tmp & HOST_RESET) {
|
||||
dev_err(host->dev, "Controller reset failed (0x%x)\n",
|
||||
tmp);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/* turn on AHCI mode */
|
||||
ahci_enable_ahci(mmio);
|
||||
/* Turn on AHCI mode */
|
||||
ahci_enable_ahci(mmio);
|
||||
|
||||
/* Some registers might be cleared on reset. Restore
|
||||
* initial values.
|
||||
*/
|
||||
if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO))
|
||||
ahci_restore_initial_config(host);
|
||||
} else
|
||||
dev_info(host->dev, "skipping global host reset\n");
|
||||
/* Some registers might be cleared on reset. Restore initial values. */
|
||||
if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO))
|
||||
ahci_restore_initial_config(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3802,11 +3802,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
|
|||
return -ENODEV;
|
||||
|
||||
/* fail early if !ATA && !ATAPI to avoid issuing [P]IDENTIFY to PMP */
|
||||
if (ata_class_enabled(new_class) &&
|
||||
new_class != ATA_DEV_ATA &&
|
||||
new_class != ATA_DEV_ATAPI &&
|
||||
new_class != ATA_DEV_ZAC &&
|
||||
new_class != ATA_DEV_SEMB) {
|
||||
if (ata_class_enabled(new_class) && new_class == ATA_DEV_PMP) {
|
||||
ata_dev_info(dev, "class mismatch %u != %u\n",
|
||||
dev->class, new_class);
|
||||
rc = -ENODEV;
|
||||
|
@ -6142,13 +6138,11 @@ EXPORT_SYMBOL_GPL(ata_pci_device_resume);
|
|||
* LOCKING:
|
||||
* Inherited from platform layer (may sleep).
|
||||
*/
|
||||
int ata_platform_remove_one(struct platform_device *pdev)
|
||||
void ata_platform_remove_one(struct platform_device *pdev)
|
||||
{
|
||||
struct ata_host *host = platform_get_drvdata(pdev);
|
||||
|
||||
ata_host_detach(host);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_platform_remove_one);
|
||||
|
||||
|
|
|
@ -1817,9 +1817,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev,
|
|||
verdict = ata_eh_speed_down_verdict(dev);
|
||||
|
||||
/* turn off NCQ? */
|
||||
if ((verdict & ATA_EH_SPDN_NCQ_OFF) &&
|
||||
(dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ |
|
||||
ATA_DFLAG_NCQ_OFF)) == ATA_DFLAG_NCQ) {
|
||||
if ((verdict & ATA_EH_SPDN_NCQ_OFF) && ata_ncq_enabled(dev)) {
|
||||
dev->flags |= ATA_DFLAG_NCQ_OFF;
|
||||
ata_dev_warn(dev, "NCQ disabled due to excessive errors\n");
|
||||
goto done;
|
||||
|
@ -3813,16 +3811,29 @@ void ata_eh_finish(struct ata_port *ap)
|
|||
* generate sense data in this function,
|
||||
* considering both err_mask and tf.
|
||||
*/
|
||||
if (qc->flags & ATA_QCFLAG_RETRY)
|
||||
if (qc->flags & ATA_QCFLAG_RETRY) {
|
||||
/*
|
||||
* Since qc->err_mask is set, ata_eh_qc_retry()
|
||||
* will not increment scmd->allowed, so upper
|
||||
* layer will only retry the command if it has
|
||||
* not already been retried too many times.
|
||||
*/
|
||||
ata_eh_qc_retry(qc);
|
||||
else
|
||||
} else {
|
||||
ata_eh_qc_complete(qc);
|
||||
}
|
||||
} else {
|
||||
if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
|
||||
ata_eh_qc_complete(qc);
|
||||
} else {
|
||||
/* feed zero TF to sense generation */
|
||||
memset(&qc->result_tf, 0, sizeof(qc->result_tf));
|
||||
/*
|
||||
* Since qc->err_mask is not set,
|
||||
* ata_eh_qc_retry() will increment
|
||||
* scmd->allowed, so upper layer is guaranteed
|
||||
* to retry the command.
|
||||
*/
|
||||
ata_eh_qc_retry(qc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1023,7 +1023,6 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
|
|||
/**
|
||||
* ata_change_queue_depth - Set a device maximum queue depth
|
||||
* @ap: ATA port of the target device
|
||||
* @dev: target ATA device
|
||||
* @sdev: SCSI device to configure queue depth for
|
||||
* @queue_depth: new queue depth
|
||||
*
|
||||
|
@ -1031,33 +1030,47 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
|
|||
* and libata.
|
||||
*
|
||||
*/
|
||||
int ata_change_queue_depth(struct ata_port *ap, struct ata_device *dev,
|
||||
struct scsi_device *sdev, int queue_depth)
|
||||
int ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
|
||||
int queue_depth)
|
||||
{
|
||||
struct ata_device *dev;
|
||||
unsigned long flags;
|
||||
int max_queue_depth;
|
||||
|
||||
if (!dev || !ata_dev_enabled(dev))
|
||||
return sdev->queue_depth;
|
||||
|
||||
if (queue_depth < 1 || queue_depth == sdev->queue_depth)
|
||||
return sdev->queue_depth;
|
||||
|
||||
/* NCQ enabled? */
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
dev->flags &= ~ATA_DFLAG_NCQ_OFF;
|
||||
if (queue_depth == 1 || !ata_ncq_enabled(dev)) {
|
||||
|
||||
dev = ata_scsi_find_dev(ap, sdev);
|
||||
if (!dev || queue_depth < 1 || queue_depth == sdev->queue_depth) {
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
return sdev->queue_depth;
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the queue depth requested does not exceed the device
|
||||
* capabilities.
|
||||
*/
|
||||
max_queue_depth = min(ATA_MAX_QUEUE, sdev->host->can_queue);
|
||||
max_queue_depth = min(max_queue_depth, ata_id_queue_depth(dev->id));
|
||||
if (queue_depth > max_queue_depth) {
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If NCQ is not supported by the device or if the target queue depth
|
||||
* is 1 (to disable drive side command queueing), turn off NCQ.
|
||||
*/
|
||||
if (queue_depth == 1 || !ata_ncq_supported(dev)) {
|
||||
dev->flags |= ATA_DFLAG_NCQ_OFF;
|
||||
queue_depth = 1;
|
||||
} else {
|
||||
dev->flags &= ~ATA_DFLAG_NCQ_OFF;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
|
||||
/* limit and apply queue depth */
|
||||
queue_depth = min(queue_depth, sdev->host->can_queue);
|
||||
queue_depth = min(queue_depth, ata_id_queue_depth(dev->id));
|
||||
queue_depth = min(queue_depth, ATA_MAX_QUEUE);
|
||||
|
||||
if (sdev->queue_depth == queue_depth)
|
||||
return -EINVAL;
|
||||
if (queue_depth == sdev->queue_depth)
|
||||
return sdev->queue_depth;
|
||||
|
||||
return scsi_change_queue_depth(sdev, queue_depth);
|
||||
}
|
||||
|
@ -1082,8 +1095,7 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
|
|||
{
|
||||
struct ata_port *ap = ata_shost_to_port(sdev->host);
|
||||
|
||||
return ata_change_queue_depth(ap, ata_scsi_find_dev(ap, sdev),
|
||||
sdev, queue_depth);
|
||||
return ata_change_queue_depth(ap, sdev, queue_depth);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);
|
||||
|
||||
|
|
|
@ -1122,7 +1122,7 @@ int ata_scsi_dev_config(struct scsi_device *sdev, struct ata_device *dev)
|
|||
if (dev->flags & ATA_DFLAG_AN)
|
||||
set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events);
|
||||
|
||||
if (dev->flags & ATA_DFLAG_NCQ)
|
||||
if (ata_ncq_supported(dev))
|
||||
depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id));
|
||||
depth = min(ATA_MAX_QUEUE, depth);
|
||||
scsi_change_queue_depth(sdev, depth);
|
||||
|
|
|
@ -303,7 +303,7 @@ static struct platform_driver ixp4xx_pata_platform_driver = {
|
|||
.of_match_table = ixp4xx_pata_of_match,
|
||||
},
|
||||
.probe = ixp4xx_pata_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
};
|
||||
|
||||
module_platform_driver(ixp4xx_pata_platform_driver);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/irq.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
|
@ -804,9 +805,7 @@ static int octeon_cf_probe(struct platform_device *pdev)
|
|||
struct resource *res_cs0, *res_cs1;
|
||||
|
||||
bool is_16bit;
|
||||
const __be32 *cs_num;
|
||||
struct property *reg_prop;
|
||||
int n_addr, n_size, reg_len;
|
||||
u64 reg;
|
||||
struct device_node *node;
|
||||
void __iomem *cs0;
|
||||
void __iomem *cs1 = NULL;
|
||||
|
@ -834,15 +833,10 @@ static int octeon_cf_probe(struct platform_device *pdev)
|
|||
else
|
||||
is_16bit = false;
|
||||
|
||||
n_addr = of_n_addr_cells(node);
|
||||
n_size = of_n_size_cells(node);
|
||||
|
||||
reg_prop = of_find_property(node, "reg", ®_len);
|
||||
if (!reg_prop || reg_len < sizeof(__be32))
|
||||
return -EINVAL;
|
||||
|
||||
cs_num = reg_prop->value;
|
||||
cf_port->cs0 = be32_to_cpup(cs_num);
|
||||
rv = of_property_read_reg(node, 0, ®, NULL);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
cf_port->cs0 = upper_32_bits(reg);
|
||||
|
||||
if (cf_port->is_true_ide) {
|
||||
struct device_node *dma_node;
|
||||
|
@ -884,13 +878,12 @@ static int octeon_cf_probe(struct platform_device *pdev)
|
|||
cs1 = devm_ioremap(&pdev->dev, res_cs1->start,
|
||||
resource_size(res_cs1));
|
||||
if (!cs1)
|
||||
return rv;
|
||||
|
||||
if (reg_len < (n_addr + n_size + 1) * sizeof(__be32))
|
||||
return -EINVAL;
|
||||
|
||||
cs_num += n_addr + n_size;
|
||||
cf_port->cs1 = be32_to_cpup(cs_num);
|
||||
rv = of_property_read_reg(node, 1, ®, NULL);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
cf_port->cs1 = upper_32_bits(reg);
|
||||
}
|
||||
|
||||
res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
|
|
|
@ -89,7 +89,7 @@ static struct platform_driver pata_of_platform_driver = {
|
|||
.of_match_table = pata_of_platform_match,
|
||||
},
|
||||
.probe = pata_of_platform_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
};
|
||||
|
||||
module_platform_driver(pata_of_platform_driver);
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
/*
|
||||
aten.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License.
|
||||
|
||||
aten.c is a low-level protocol driver for the ATEN EH-100
|
||||
parallel port adapter. The EH-100 supports 4-bit and 8-bit
|
||||
modes only. There is also an EH-132 which supports EPP mode
|
||||
transfers. The EH-132 is not yet supported.
|
||||
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* aten.c is a low-level protocol driver for the ATEN EH-100
|
||||
* parallel port adapter. The EH-100 supports 4-bit and 8-bit
|
||||
* modes only. There is also an EH-132 which supports EPP mode
|
||||
* transfers. The EH-132 is not yet supported.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -20,36 +19,36 @@
|
|||
|
||||
#define j44(a,b) ((((a>>4)&0x0f)|(b&0xf0))^0x88)
|
||||
|
||||
/* cont = 0 - access the IDE register file
|
||||
cont = 1 - access the IDE command set
|
||||
*/
|
||||
|
||||
/*
|
||||
* cont = 0 - access the IDE register file
|
||||
* cont = 1 - access the IDE command set
|
||||
*/
|
||||
static int cont_map[2] = { 0x08, 0x20 };
|
||||
|
||||
static void aten_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
|
||||
{ int r;
|
||||
|
||||
r = regr + cont_map[cont] + 0x80;
|
||||
{
|
||||
int r = regr + cont_map[cont] + 0x80;
|
||||
|
||||
w0(r); w2(0xe); w2(6); w0(val); w2(7); w2(6); w2(0xc);
|
||||
}
|
||||
|
||||
static int aten_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
{
|
||||
int a, b, r;
|
||||
|
||||
{ int a, b, r;
|
||||
|
||||
r = regr + cont_map[cont] + 0x40;
|
||||
r = regr + cont_map[cont] + 0x40;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w0(r); w2(0xe); w2(6);
|
||||
case 0:
|
||||
w0(r); w2(0xe); w2(6);
|
||||
w2(7); w2(6); w2(0);
|
||||
a = r1(); w0(0x10); b = r1(); w2(0xc);
|
||||
return j44(a,b);
|
||||
|
||||
case 1: r |= 0x10;
|
||||
w0(r); w2(0xe); w2(6); w0(0xff);
|
||||
case 1:
|
||||
r |= 0x10;
|
||||
w0(r); w2(0xe); w2(6); w0(0xff);
|
||||
w2(0x27); w2(0x26); w2(0x20);
|
||||
a = r0();
|
||||
w2(0x26); w2(0xc);
|
||||
|
@ -59,27 +58,30 @@ static int aten_read_regr(struct pi_adapter *pi, int cont, int regr)
|
|||
}
|
||||
|
||||
static void aten_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int k, a, b, c, d;
|
||||
{
|
||||
int k, a, b, c, d;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w0(0x48); w2(0xe); w2(6);
|
||||
for (k=0;k<count/2;k++) {
|
||||
case 0:
|
||||
w0(0x48); w2(0xe); w2(6);
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w2(7); w2(6); w2(2);
|
||||
a = r1(); w0(0x58); b = r1();
|
||||
w2(0); d = r1(); w0(0x48); c = r1();
|
||||
buf[2*k] = j44(c,d);
|
||||
buf[2*k+1] = j44(a,b);
|
||||
buf[2 * k] = j44(c, d);
|
||||
buf[2 * k + 1] = j44(a, b);
|
||||
}
|
||||
w2(0xc);
|
||||
break;
|
||||
|
||||
case 1: w0(0x58); w2(0xe); w2(6);
|
||||
for (k=0;k<count/2;k++) {
|
||||
case 1:
|
||||
w0(0x58); w2(0xe); w2(6);
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w2(0x27); w2(0x26); w2(0x22);
|
||||
a = r0(); w2(0x20); b = r0();
|
||||
buf[2*k] = b; buf[2*k+1] = a;
|
||||
buf[2 * k] = b;
|
||||
buf[2 * k + 1] = a;
|
||||
}
|
||||
w2(0x26); w2(0xc);
|
||||
break;
|
||||
|
@ -87,36 +89,37 @@ static void aten_read_block(struct pi_adapter *pi, char *buf, int count)
|
|||
}
|
||||
|
||||
static void aten_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int k;
|
||||
{
|
||||
int k;
|
||||
|
||||
w0(0x88); w2(0xe); w2(6);
|
||||
for (k=0;k<count/2;k++) {
|
||||
w0(buf[2*k+1]); w2(0xe); w2(6);
|
||||
w0(buf[2*k]); w2(7); w2(6);
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w0(buf[2 * k + 1]); w2(0xe); w2(6);
|
||||
w0(buf[2 * k]); w2(7); w2(6);
|
||||
}
|
||||
w2(0xc);
|
||||
}
|
||||
|
||||
static void aten_connect(struct pi_adapter *pi)
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(0xc);
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(0xc);
|
||||
}
|
||||
|
||||
static void aten_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
{
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
static void aten_log_adapter(struct pi_adapter *pi)
|
||||
{
|
||||
char *mode_string[2] = { "4-bit", "8-bit" };
|
||||
|
||||
{ char *mode_string[2] = {"4-bit","8-bit"};
|
||||
|
||||
dev_info(&pi->dev, "ATEN EH-100 at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
dev_info(&pi->dev,
|
||||
"ATEN EH-100 at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
}
|
||||
|
||||
static struct pi_protocol aten = {
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/*
|
||||
bpck.c (c) 1996-8 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License.
|
||||
|
||||
bpck.c is a low-level protocol driver for the MicroSolutions
|
||||
"backpack" parallel port IDE adapter.
|
||||
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* (c) 1996-1998 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* bpck.c is a low-level protocol driver for the MicroSolutions
|
||||
* "backpack" parallel port IDE adapter.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -29,59 +28,57 @@
|
|||
|
||||
#define j44(l,h) (((l>>3)&0x7)|((l>>4)&0x8)|((h<<1)&0x70)|(h&0x80))
|
||||
|
||||
/* cont = 0 - access the IDE register file
|
||||
cont = 1 - access the IDE command set
|
||||
cont = 2 - use internal bpck register addressing
|
||||
*/
|
||||
|
||||
/*
|
||||
* cont = 0 - access the IDE register file
|
||||
* cont = 1 - access the IDE command set
|
||||
* cont = 2 - use internal bpck register addressing
|
||||
*/
|
||||
static int cont_map[3] = { 0x40, 0x48, 0 };
|
||||
|
||||
static int bpck_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
|
||||
{ int r, l, h;
|
||||
{
|
||||
int r, l, h;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w0(r & 0xf); w0(r); t2(2); t2(4);
|
||||
case 0:
|
||||
w0(r & 0xf); w0(r); t2(2); t2(4);
|
||||
l = r1();
|
||||
t2(4);
|
||||
h = r1();
|
||||
return j44(l,h);
|
||||
|
||||
case 1: w0(r & 0xf); w0(r); t2(2);
|
||||
e2(); t2(0x20);
|
||||
t2(4);
|
||||
h = r1();
|
||||
return j44(l, h);
|
||||
case 1:
|
||||
w0(r & 0xf); w0(r); t2(2);
|
||||
e2(); t2(0x20);
|
||||
t2(4); h = r0();
|
||||
t2(1); t2(0x20);
|
||||
return h;
|
||||
|
||||
t2(1); t2(0x20);
|
||||
return h;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4: w0(r); w2(9); w2(0); w2(0x20);
|
||||
case 4:
|
||||
w0(r); w2(9); w2(0); w2(0x20);
|
||||
h = r4();
|
||||
w2(0);
|
||||
return h;
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void bpck_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
|
||||
{ int r;
|
||||
{
|
||||
int r;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1: w0(r);
|
||||
t2(2);
|
||||
w0(val);
|
||||
o2(); t2(4); t2(1);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
case 4: w0(r); w2(9); w2(0);
|
||||
|
@ -97,210 +94,249 @@ static void bpck_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
|||
#define RR(r) (bpck_read_regr(pi,2,r))
|
||||
|
||||
static void bpck_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int i;
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: WR(4,0x40);
|
||||
case 0:
|
||||
WR(4, 0x40);
|
||||
w0(0x40); t2(2); t2(1);
|
||||
for (i=0;i<count;i++) { w0(buf[i]); t2(4); }
|
||||
WR(4,0);
|
||||
for (i = 0; i < count; i++) {
|
||||
w0(buf[i]);
|
||||
t2(4);
|
||||
}
|
||||
WR(4, 0);
|
||||
break;
|
||||
|
||||
case 1: WR(4,0x50);
|
||||
w0(0x40); t2(2); t2(1);
|
||||
for (i=0;i<count;i++) { w0(buf[i]); t2(4); }
|
||||
WR(4,0x10);
|
||||
case 1:
|
||||
WR(4, 0x50);
|
||||
w0(0x40); t2(2); t2(1);
|
||||
for (i = 0; i < count; i++) {
|
||||
w0(buf[i]);
|
||||
t2(4);
|
||||
}
|
||||
WR(4, 0x10);
|
||||
break;
|
||||
|
||||
case 2: WR(4,0x48);
|
||||
case 2:
|
||||
WR(4, 0x48);
|
||||
w0(0x40); w2(9); w2(0); w2(1);
|
||||
for (i=0;i<count;i++) w4(buf[i]);
|
||||
for (i = 0; i < count; i++)
|
||||
w4(buf[i]);
|
||||
w2(0);
|
||||
WR(4,8);
|
||||
WR(4, 8);
|
||||
break;
|
||||
|
||||
case 3: WR(4,0x48);
|
||||
w0(0x40); w2(9); w2(0); w2(1);
|
||||
for (i=0;i<count/2;i++) w4w(((u16 *)buf)[i]);
|
||||
w2(0);
|
||||
WR(4,8);
|
||||
break;
|
||||
|
||||
case 4: WR(4,0x48);
|
||||
w0(0x40); w2(9); w2(0); w2(1);
|
||||
for (i=0;i<count/4;i++) w4l(((u32 *)buf)[i]);
|
||||
w2(0);
|
||||
WR(4,8);
|
||||
break;
|
||||
case 3:
|
||||
WR(4, 0x48);
|
||||
w0(0x40); w2(9); w2(0); w2(1);
|
||||
for (i = 0; i < count / 2; i++)
|
||||
w4w(((u16 *)buf)[i]);
|
||||
w2(0);
|
||||
WR(4, 8);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
WR(4, 0x48);
|
||||
w0(0x40); w2(9); w2(0); w2(1);
|
||||
for (i = 0; i < count / 4; i++)
|
||||
w4l(((u32 *)buf)[i]);
|
||||
w2(0);
|
||||
WR(4, 8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void bpck_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int i, l, h;
|
||||
{
|
||||
int i, l, h;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: WR(4,0x40);
|
||||
case 0:
|
||||
WR(4, 0x40);
|
||||
w0(0x40); t2(2);
|
||||
for (i=0;i<count;i++) {
|
||||
t2(4); l = r1();
|
||||
t2(4); h = r1();
|
||||
buf[i] = j44(l,h);
|
||||
for (i = 0; i < count; i++) {
|
||||
t2(4); l = r1();
|
||||
t2(4); h = r1();
|
||||
buf[i] = j44(l, h);
|
||||
}
|
||||
WR(4,0);
|
||||
WR(4, 0);
|
||||
break;
|
||||
|
||||
case 1: WR(4,0x50);
|
||||
case 1:
|
||||
WR(4, 0x50);
|
||||
w0(0x40); t2(2); t2(0x20);
|
||||
for(i=0;i<count;i++) { t2(4); buf[i] = r0(); }
|
||||
t2(1); t2(0x20);
|
||||
WR(4,0x10);
|
||||
for (i = 0; i < count; i++) {
|
||||
t2(4);
|
||||
buf[i] = r0();
|
||||
}
|
||||
t2(1); t2(0x20);
|
||||
WR(4, 0x10);
|
||||
break;
|
||||
|
||||
case 2: WR(4,0x48);
|
||||
case 2:
|
||||
WR(4, 0x48);
|
||||
w0(0x40); w2(9); w2(0); w2(0x20);
|
||||
for (i=0;i<count;i++) buf[i] = r4();
|
||||
for (i = 0; i < count; i++)
|
||||
buf[i] = r4();
|
||||
w2(0);
|
||||
WR(4,8);
|
||||
WR(4, 8);
|
||||
break;
|
||||
|
||||
case 3: WR(4,0x48);
|
||||
w0(0x40); w2(9); w2(0); w2(0x20);
|
||||
for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w();
|
||||
w2(0);
|
||||
WR(4,8);
|
||||
break;
|
||||
case 3:
|
||||
WR(4, 0x48);
|
||||
w0(0x40); w2(9); w2(0); w2(0x20);
|
||||
for (i = 0; i < count / 2; i++)
|
||||
((u16 *)buf)[i] = r4w();
|
||||
w2(0);
|
||||
WR(4, 8);
|
||||
break;
|
||||
|
||||
case 4: WR(4,0x48);
|
||||
w0(0x40); w2(9); w2(0); w2(0x20);
|
||||
for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l();
|
||||
w2(0);
|
||||
WR(4,8);
|
||||
break;
|
||||
case 4:
|
||||
WR(4, 0x48);
|
||||
w0(0x40); w2(9); w2(0); w2(0x20);
|
||||
for (i = 0; i < count / 4; i++)
|
||||
((u32 *)buf)[i] = r4l();
|
||||
w2(0);
|
||||
WR(4, 8);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int bpck_probe_unit(struct pi_adapter *pi)
|
||||
|
||||
{ int o1, o0, f7, id;
|
||||
{
|
||||
int o1, o0, f7, id;
|
||||
int t, s;
|
||||
|
||||
id = pi->unit;
|
||||
s = 0;
|
||||
w2(4); w2(0xe); r2(); t2(2);
|
||||
w2(4); w2(0xe); r2(); t2(2);
|
||||
o1 = r1()&0xf8;
|
||||
o0 = r0();
|
||||
w0(255-id); w2(4); w0(id);
|
||||
t2(8); t2(8); t2(8);
|
||||
t2(2); t = r1()&0xf8;
|
||||
f7 = ((id % 8) == 7);
|
||||
if ((f7) || (t != o1)) { t2(2); s = r1()&0xf8; }
|
||||
if ((f7) || (t != o1)) {
|
||||
t2(2);
|
||||
s = r1() & 0xf8;
|
||||
}
|
||||
if ((t == o1) && ((!f7) || (s == o1))) {
|
||||
w2(0x4c); w0(o0);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
t2(8); w0(0); t2(2); w2(0x4c); w0(o0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void bpck_connect(struct pi_adapter *pi)
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
w0(0xff-pi->unit); w2(4); w0(pi->unit);
|
||||
t2(8); t2(8); t2(8);
|
||||
t2(8); t2(8); t2(8);
|
||||
t2(2); t2(2);
|
||||
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: t2(8); WR(4,0);
|
||||
case 0:
|
||||
t2(8); WR(4, 0);
|
||||
break;
|
||||
|
||||
case 1: t2(8); WR(4,0x10);
|
||||
case 1:
|
||||
t2(8); WR(4, 0x10);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
case 4: w2(0); WR(4,8);
|
||||
case 3:
|
||||
case 4:
|
||||
w2(0); WR(4, 8);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
WR(5,8);
|
||||
|
||||
/* if (pi->devtype == PI_PCD) { possibly wrong, purpose unknown */
|
||||
WR(0x46,0x10); /* fiddle with ESS logic ??? */
|
||||
WR(0x4c,0x38);
|
||||
WR(0x4d,0x88);
|
||||
WR(0x46,0xa0);
|
||||
WR(0x41,0);
|
||||
WR(0x4e,8);
|
||||
/* }*/
|
||||
/*
|
||||
* Possibly wrong, purpose unknown (fiddle with ESS logic ???)
|
||||
* if (pi->devtype == PI_PCD) {
|
||||
*/
|
||||
WR(0x46, 0x10);
|
||||
WR(0x4c, 0x38);
|
||||
WR(0x4d, 0x88);
|
||||
WR(0x46, 0xa0);
|
||||
WR(0x41, 0);
|
||||
WR(0x4e, 8);
|
||||
/* } */
|
||||
}
|
||||
|
||||
static void bpck_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ w0(0);
|
||||
if (pi->mode >= 2) { w2(9); w2(0); } else t2(2);
|
||||
{
|
||||
w0(0);
|
||||
if (pi->mode >= 2) {
|
||||
w2(9); w2(0);
|
||||
} else {
|
||||
t2(2);
|
||||
}
|
||||
w2(0x4c); w0(pi->saved_r0);
|
||||
}
|
||||
}
|
||||
|
||||
static void bpck_force_spp(struct pi_adapter *pi)
|
||||
{
|
||||
/* This fakes the EPP protocol to turn off EPP ... */
|
||||
pi->saved_r0 = r0();
|
||||
w0(0xff-pi->unit); w2(4); w0(pi->unit);
|
||||
t2(8); t2(8); t2(8);
|
||||
t2(2); t2(2);
|
||||
|
||||
/* This fakes the EPP protocol to turn off EPP ... */
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
w0(0xff-pi->unit); w2(4); w0(pi->unit);
|
||||
t2(8); t2(8); t2(8);
|
||||
t2(2); t2(2);
|
||||
|
||||
w2(0);
|
||||
w0(4); w2(9); w2(0);
|
||||
w0(0); w2(1); w2(3); w2(0);
|
||||
w0(0); w2(9); w2(0);
|
||||
w2(0x4c); w0(pi->saved_r0);
|
||||
w2(0);
|
||||
w0(4); w2(9); w2(0);
|
||||
w0(0); w2(1); w2(3); w2(0);
|
||||
w0(0); w2(9); w2(0);
|
||||
w2(0x4c); w0(pi->saved_r0);
|
||||
}
|
||||
|
||||
#define TEST_LEN 16
|
||||
|
||||
static int bpck_test_proto(struct pi_adapter *pi)
|
||||
|
||||
{ int i, e, l, h, om;
|
||||
{
|
||||
int i, e, l, h, om;
|
||||
char buf[TEST_LEN];
|
||||
|
||||
bpck_force_spp(pi);
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: bpck_connect(pi);
|
||||
WR(0x13,0x7f);
|
||||
case 0:
|
||||
bpck_connect(pi);
|
||||
WR(0x13, 0x7f);
|
||||
w0(0x13); t2(2);
|
||||
for(i=0;i<TEST_LEN;i++) {
|
||||
t2(4); l = r1();
|
||||
t2(4); h = r1();
|
||||
buf[i] = j44(l,h);
|
||||
for (i = 0; i < TEST_LEN; i++) {
|
||||
t2(4); l = r1();
|
||||
t2(4); h = r1();
|
||||
buf[i] = j44(l, h);
|
||||
}
|
||||
bpck_disconnect(pi);
|
||||
break;
|
||||
|
||||
case 1: bpck_connect(pi);
|
||||
WR(0x13,0x7f);
|
||||
w0(0x13); t2(2); t2(0x20);
|
||||
for(i=0;i<TEST_LEN;i++) { t2(4); buf[i] = r0(); }
|
||||
t2(1); t2(0x20);
|
||||
case 1:
|
||||
bpck_connect(pi);
|
||||
WR(0x13, 0x7f);
|
||||
w0(0x13); t2(2); t2(0x20);
|
||||
for (i = 0; i < TEST_LEN; i++) {
|
||||
t2(4);
|
||||
buf[i] = r0();
|
||||
}
|
||||
t2(1); t2(0x20);
|
||||
bpck_disconnect(pi);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
case 4: om = pi->mode;
|
||||
case 4:
|
||||
om = pi->mode;
|
||||
pi->mode = 0;
|
||||
bpck_connect(pi);
|
||||
WR(7,3);
|
||||
WR(4,8);
|
||||
WR(7, 3);
|
||||
WR(4, 8);
|
||||
bpck_disconnect(pi);
|
||||
|
||||
pi->mode = om;
|
||||
|
@ -308,34 +344,44 @@ static int bpck_test_proto(struct pi_adapter *pi)
|
|||
w0(0x13); w2(9); w2(1); w0(0); w2(3); w2(0); w2(0xe0);
|
||||
|
||||
switch (pi->mode) {
|
||||
case 2: for (i=0;i<TEST_LEN;i++) buf[i] = r4();
|
||||
break;
|
||||
case 3: for (i=0;i<TEST_LEN/2;i++) ((u16 *)buf)[i] = r4w();
|
||||
break;
|
||||
case 4: for (i=0;i<TEST_LEN/4;i++) ((u32 *)buf)[i] = r4l();
|
||||
break;
|
||||
case 2:
|
||||
for (i = 0; i < TEST_LEN; i++)
|
||||
buf[i] = r4();
|
||||
break;
|
||||
case 3:
|
||||
for (i = 0; i < TEST_LEN / 2; i++)
|
||||
((u16 *)buf)[i] = r4w();
|
||||
break;
|
||||
case 4:
|
||||
for (i = 0; i < TEST_LEN / 4; i++)
|
||||
((u32 *)buf)[i] = r4l();
|
||||
break;
|
||||
}
|
||||
|
||||
w2(0);
|
||||
WR(7,0);
|
||||
WR(7, 0);
|
||||
bpck_disconnect(pi);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
dev_dbg(&pi->dev, "bpck: 0x%x unit %d mode %d: ",
|
||||
pi->port, pi->unit, pi->mode);
|
||||
print_hex_dump_debug("bpck: ", DUMP_PREFIX_NONE, TEST_LEN, 1, buf, TEST_LEN, false);
|
||||
print_hex_dump_debug("bpck: ", DUMP_PREFIX_NONE, TEST_LEN, 1, buf,
|
||||
TEST_LEN, false);
|
||||
|
||||
e = 0;
|
||||
for (i=0;i<TEST_LEN;i++) if (buf[i] != (i+1)) e++;
|
||||
for (i = 0; i < TEST_LEN; i++) {
|
||||
if (buf[i] != i + 1)
|
||||
e++;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static void bpck_read_eeprom(struct pi_adapter *pi, char *buf)
|
||||
|
||||
{ int i, j, k, p, v, f, om, od;
|
||||
{
|
||||
int i, j, k, p, v, f, om, od;
|
||||
|
||||
bpck_force_spp(pi);
|
||||
|
||||
|
@ -343,77 +389,97 @@ static void bpck_read_eeprom(struct pi_adapter *pi, char *buf)
|
|||
pi->mode = 0; pi->delay = 6;
|
||||
|
||||
bpck_connect(pi);
|
||||
|
||||
WR(4,0);
|
||||
for (i=0;i<64;i++) {
|
||||
WR(6,8);
|
||||
WR(6,0xc);
|
||||
p = 0x100;
|
||||
for (k=0;k<9;k++) {
|
||||
f = (((i + 0x180) & p) != 0) * 2;
|
||||
WR(6,f+0xc);
|
||||
WR(6,f+0xd);
|
||||
WR(6,f+0xc);
|
||||
p = (p >> 1);
|
||||
}
|
||||
for (j=0;j<2;j++) {
|
||||
v = 0;
|
||||
for (k=0;k<8;k++) {
|
||||
WR(6,0xc);
|
||||
WR(6,0xd);
|
||||
WR(6,0xc);
|
||||
f = RR(0);
|
||||
v = 2*v + (f == 0x84);
|
||||
|
||||
WR(4, 0);
|
||||
for (i = 0; i < 64; i++) {
|
||||
WR(6, 8);
|
||||
WR(6, 0xc);
|
||||
p = 0x100;
|
||||
for (k = 0; k < 9; k++) {
|
||||
f = (((i + 0x180) & p) != 0) * 2;
|
||||
WR(6, f + 0xc);
|
||||
WR(6, f + 0xd);
|
||||
WR(6, f + 0xc);
|
||||
p = (p >> 1);
|
||||
}
|
||||
for (j = 0; j < 2; j++) {
|
||||
v = 0;
|
||||
for (k = 0; k < 8; k++) {
|
||||
WR(6, 0xc);
|
||||
WR(6, 0xd);
|
||||
WR(6, 0xc);
|
||||
f = RR(0);
|
||||
v = 2 * v + (f == 0x84);
|
||||
}
|
||||
buf[2 * i + 1 - j] = v;
|
||||
}
|
||||
buf[2*i+1-j] = v;
|
||||
}
|
||||
}
|
||||
WR(6,8);
|
||||
WR(6,0);
|
||||
WR(5,8);
|
||||
WR(6, 8);
|
||||
WR(6, 0);
|
||||
WR(5, 8);
|
||||
|
||||
bpck_disconnect(pi);
|
||||
|
||||
if (om >= 2) {
|
||||
bpck_connect(pi);
|
||||
WR(7,3);
|
||||
WR(4,8);
|
||||
bpck_disconnect(pi);
|
||||
bpck_connect(pi);
|
||||
WR(7, 3);
|
||||
WR(4, 8);
|
||||
bpck_disconnect(pi);
|
||||
}
|
||||
|
||||
pi->mode = om; pi->delay = od;
|
||||
}
|
||||
|
||||
static int bpck_test_port(struct pi_adapter *pi) /* check for 8-bit port */
|
||||
|
||||
{ int i, r, m;
|
||||
static int bpck_test_port(struct pi_adapter *pi)
|
||||
{
|
||||
int i, r, m;
|
||||
|
||||
/* Check for 8-bit port */
|
||||
w2(0x2c); i = r0(); w0(255-i); r = r0(); w0(i);
|
||||
m = -1;
|
||||
if (r == i) m = 2;
|
||||
if (r == (255-i)) m = 0;
|
||||
if (r == i)
|
||||
m = 2;
|
||||
if (r == (255-i))
|
||||
m = 0;
|
||||
|
||||
w2(0xc); i = r0(); w0(255-i); r = r0(); w0(i);
|
||||
if (r != (255-i)) m = -1;
|
||||
|
||||
if (m == 0) { w2(6); w2(0xc); r = r0(); w0(0xaa); w0(r); w0(0xaa); }
|
||||
if (m == 2) { w2(0x26); w2(0xc); }
|
||||
w2(0xc);
|
||||
i = r0();
|
||||
w0(255-i);
|
||||
r = r0();
|
||||
w0(i);
|
||||
if (r != (255-i))
|
||||
m = -1;
|
||||
|
||||
if (m == 0) {
|
||||
w2(6);
|
||||
w2(0xc);
|
||||
r = r0();
|
||||
w0(0xaa);
|
||||
w0(r);
|
||||
w0(0xaa);
|
||||
}
|
||||
if (m == 2) {
|
||||
w2(0x26);
|
||||
w2(0xc);
|
||||
}
|
||||
|
||||
if (m == -1)
|
||||
return 0;
|
||||
|
||||
if (m == -1) return 0;
|
||||
return 5;
|
||||
}
|
||||
|
||||
static void bpck_log_adapter(struct pi_adapter *pi)
|
||||
|
||||
{ char *mode_string[5] = { "4-bit","8-bit","EPP-8",
|
||||
"EPP-16","EPP-32" };
|
||||
{
|
||||
char *mode_str[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
|
||||
char scratch[128];
|
||||
|
||||
bpck_read_eeprom(pi,scratch);
|
||||
print_hex_dump_bytes("bpck EEPROM: ", DUMP_PREFIX_NONE, scratch, 128);
|
||||
dev_info(&pi->dev, "backpack %8.8s unit %d at 0x%x, mode %d (%s), delay %d\n",
|
||||
dev_info(&pi->dev,
|
||||
"backpack %8.8s unit %d at 0x%x, mode %d (%s), delay %d\n",
|
||||
&scratch[110], pi->unit, pi->port, pi->mode,
|
||||
mode_string[pi->mode], pi->delay);
|
||||
mode_str[pi->mode], pi->delay);
|
||||
}
|
||||
|
||||
static struct pi_protocol bpck = {
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
backpack.c (c) 2001 Micro Solutions Inc.
|
||||
Released under the terms of the GNU General Public license
|
||||
|
||||
backpack.c is a low-level protocol driver for the Micro Solutions
|
||||
"BACKPACK" parallel port IDE adapter
|
||||
(Works on Series 6 drives)
|
||||
|
||||
Written by: Ken Hahn (linux-dev@micro-solutions.com)
|
||||
Clive Turvey (linux-dev@micro-solutions.com)
|
||||
|
||||
*/
|
||||
* (c) 2001 Micro Solutions Inc.
|
||||
*
|
||||
* backpack.c is a low-level protocol driver for the Micro Solutions
|
||||
* "BACKPACK" parallel port IDE adapter (works on Series 6 drives).
|
||||
*
|
||||
* Written by: Ken Hahn (linux-dev@micro-solutions.com)
|
||||
* Clive Turvey (linux-dev@micro-solutions.com)
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -326,11 +324,14 @@ static int bpck6_open(struct pi_adapter *pi)
|
|||
if (j != k)
|
||||
goto fail;
|
||||
|
||||
if (i & 4) // EPP
|
||||
if (i & 4) {
|
||||
/* EPP */
|
||||
parport_frob_control(pi->pardev->port,
|
||||
PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, 0);
|
||||
else // PPC/ECP
|
||||
} else {
|
||||
/* PPC/ECP */
|
||||
parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, 0);
|
||||
}
|
||||
|
||||
pi->private = 0;
|
||||
|
||||
|
@ -347,17 +348,20 @@ fail:
|
|||
parport_write_control(pi->pardev->port, pi->saved_r2);
|
||||
parport_write_data(pi->pardev->port, pi->saved_r0);
|
||||
|
||||
return 0; // FAIL
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bpck6_deselect(struct pi_adapter *pi)
|
||||
{
|
||||
if (mode_map[pi->mode] & 4) // EPP
|
||||
if (mode_map[pi->mode] & 4) {
|
||||
/* EPP */
|
||||
parport_frob_control(pi->pardev->port, PARPORT_CONTROL_INIT,
|
||||
PARPORT_CONTROL_INIT);
|
||||
else // PPC/ECP
|
||||
PARPORT_CONTROL_INIT);
|
||||
} else {
|
||||
/* PPC/ECP */
|
||||
parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT,
|
||||
PARPORT_CONTROL_SELECT);
|
||||
PARPORT_CONTROL_SELECT);
|
||||
}
|
||||
|
||||
parport_write_data(pi->pardev->port, pi->saved_r0);
|
||||
parport_write_control(pi->pardev->port,
|
||||
|
@ -386,7 +390,8 @@ static void bpck6_disconnect(struct pi_adapter *pi)
|
|||
bpck6_deselect(pi);
|
||||
}
|
||||
|
||||
static int bpck6_test_port(struct pi_adapter *pi) /* check for 8-bit port */
|
||||
/* check for 8-bit port */
|
||||
static int bpck6_test_port(struct pi_adapter *pi)
|
||||
{
|
||||
dev_dbg(&pi->dev, "PARPORT indicates modes=%x for lp=0x%lx\n",
|
||||
pi->pardev->port->modes, pi->pardev->port->base);
|
||||
|
@ -413,28 +418,26 @@ static int bpck6_probe_unit(struct pi_adapter *pi)
|
|||
|
||||
dev_dbg(&pi->dev, "ppc_open returned %2x\n", out);
|
||||
|
||||
if(out)
|
||||
{
|
||||
if (out) {
|
||||
bpck6_deselect(pi);
|
||||
dev_dbg(&pi->dev, "leaving probe\n");
|
||||
pi->mode = saved_mode;
|
||||
return(1);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dev_dbg(&pi->dev, "Failed open\n");
|
||||
pi->mode = saved_mode;
|
||||
return(0);
|
||||
}
|
||||
|
||||
dev_dbg(&pi->dev, "Failed open\n");
|
||||
pi->mode = saved_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bpck6_log_adapter(struct pi_adapter *pi)
|
||||
{
|
||||
char *mode_string[5]=
|
||||
{"4-bit","8-bit","EPP-8","EPP-16","EPP-32"};
|
||||
char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
|
||||
|
||||
dev_info(&pi->dev, "Micro Solutions BACKPACK Drive unit %d at 0x%x, mode:%d (%s), delay %d\n",
|
||||
pi->unit, pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
dev_info(&pi->dev,
|
||||
"Micro Solutions BACKPACK Drive unit %d at 0x%x, mode:%d (%s), delay %d\n",
|
||||
pi->unit, pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
}
|
||||
|
||||
static struct pi_protocol bpck6 = {
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
/*
|
||||
comm.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License.
|
||||
|
||||
comm.c is a low-level protocol driver for some older models
|
||||
of the DataStor "Commuter" parallel to IDE adapter. Some of
|
||||
the parallel port devices marketed by Arista currently
|
||||
use this adapter.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* (c) 1997-1998 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* comm.c is a low-level protocol driver for some older models of the DataStor
|
||||
* "Commuter" parallel to IDE adapter. Some of the parallel port devices
|
||||
* marketed by Arista currently use this adapter.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -17,165 +16,172 @@
|
|||
#include <asm/io.h>
|
||||
#include "pata_parport.h"
|
||||
|
||||
/* mode codes: 0 nybble reads, 8-bit writes
|
||||
1 8-bit reads and writes
|
||||
2 8-bit EPP mode
|
||||
*/
|
||||
/*
|
||||
* mode codes: 0 nybble reads, 8-bit writes
|
||||
* 1 8-bit reads and writes
|
||||
* 2 8-bit EPP mode
|
||||
*/
|
||||
|
||||
#define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0))
|
||||
#define j44(a, b) (((a >> 3) & 0x0f) | ((b << 1) & 0xf0))
|
||||
|
||||
#define P1 w2(5);w2(0xd);w2(0xd);w2(5);w2(4);
|
||||
#define P2 w2(5);w2(7);w2(7);w2(5);w2(4);
|
||||
|
||||
/* cont = 0 - access the IDE register file
|
||||
cont = 1 - access the IDE command set
|
||||
*/
|
||||
|
||||
/*
|
||||
* cont = 0 - access the IDE register file
|
||||
* cont = 1 - access the IDE command set
|
||||
*/
|
||||
static int cont_map[2] = { 0x08, 0x10 };
|
||||
|
||||
static int comm_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
|
||||
{ int l, h, r;
|
||||
{
|
||||
int l, h, r;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
|
||||
switch (pi->mode) {
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
w0(r); P1; w0(0);
|
||||
w2(6); l = r1(); w0(0x80); h = r1(); w2(4);
|
||||
return j44(l, h);
|
||||
|
||||
case 0: w0(r); P1; w0(0);
|
||||
w2(6); l = r1(); w0(0x80); h = r1(); w2(4);
|
||||
return j44(l,h);
|
||||
|
||||
case 1: w0(r+0x20); P1;
|
||||
w0(0); w2(0x26); h = r0(); w2(4);
|
||||
return h;
|
||||
case 1:
|
||||
w0(r+0x20); P1;
|
||||
w0(0); w2(0x26); h = r0(); w2(4);
|
||||
return h;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
case 4: w3(r+0x20); (void)r1();
|
||||
w2(0x24); h = r4(); w2(4);
|
||||
return h;
|
||||
case 4:
|
||||
w3(r+0x20); (void)r1();
|
||||
w2(0x24); h = r4(); w2(4);
|
||||
return h;
|
||||
}
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void comm_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
{
|
||||
int r = regr + cont_map[cont];
|
||||
|
||||
{ int r;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1: w0(r); P1; w0(val); P2;
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
w0(r); P1; w0(val); P2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
case 4: w3(r); (void)r1(); w4(val);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
w3(r); (void)r1(); w4(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void comm_connect(struct pi_adapter *pi)
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(4); w0(0xff); w2(6);
|
||||
w2(4); w0(0xaa); w2(6);
|
||||
w2(4); w0(0x00); w2(6);
|
||||
w2(4); w0(0x87); w2(6);
|
||||
w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4);
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(4); w0(0xff); w2(6);
|
||||
w2(4); w0(0xaa); w2(6);
|
||||
w2(4); w0(0x00); w2(6);
|
||||
w2(4); w0(0x87); w2(6);
|
||||
w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4);
|
||||
}
|
||||
|
||||
static void comm_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ w2(0); w2(0); w2(0); w2(4);
|
||||
{
|
||||
w2(0); w2(0); w2(0); w2(4);
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
static void comm_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int i, l, h;
|
||||
|
||||
{ int i, l, h;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w0(0x48); P1;
|
||||
for(i=0;i<count;i++) {
|
||||
w0(0); w2(6); l = r1();
|
||||
w0(0x80); h = r1(); w2(4);
|
||||
buf[i] = j44(l,h);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: w0(0x68); P1; w0(0);
|
||||
for(i=0;i<count;i++) {
|
||||
w2(0x26); buf[i] = r0(); w2(0x24);
|
||||
}
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
w0(0x48); P1;
|
||||
for (i = 0; i < count; i++) {
|
||||
w0(0); w2(6); l = r1();
|
||||
w0(0x80); h = r1(); w2(4);
|
||||
buf[i] = j44(l, h);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
w0(0x68); P1; w0(0);
|
||||
for (i = 0; i < count; i++) {
|
||||
w2(0x26);
|
||||
buf[i] = r0();
|
||||
w2(0x24);
|
||||
}
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 2: w3(0x68); (void)r1(); w2(0x24);
|
||||
for (i=0;i<count;i++) buf[i] = r4();
|
||||
case 2:
|
||||
w3(0x68); (void)r1(); w2(0x24);
|
||||
for (i = 0; i < count; i++)
|
||||
buf[i] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
case 3:
|
||||
w3(0x68); (void)r1(); w2(0x24);
|
||||
for (i = 0; i < count / 2; i++)
|
||||
((u16 *)buf)[i] = r4w();
|
||||
w2(4);
|
||||
break;
|
||||
case 4:
|
||||
w3(0x68); (void)r1(); w2(0x24);
|
||||
for (i = 0; i < count / 4; i++)
|
||||
((u32 *)buf)[i] = r4l();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 3: w3(0x68); (void)r1(); w2(0x24);
|
||||
for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 4: w3(0x68); (void)r1(); w2(0x24);
|
||||
for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* NB: Watch out for the byte swapped writes ! */
|
||||
|
||||
static void comm_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int k;
|
||||
|
||||
{ int k;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1: w0(0x68); P1;
|
||||
for (k=0;k<count;k++) {
|
||||
w2(5); w0(buf[k^1]); w2(7);
|
||||
}
|
||||
w2(5); w2(4);
|
||||
break;
|
||||
|
||||
case 2: w3(0x48); (void)r1();
|
||||
for (k=0;k<count;k++) w4(buf[k^1]);
|
||||
break;
|
||||
|
||||
case 3: w3(0x48); (void)r1();
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
w0(0x68); P1;
|
||||
for (k = 0; k < count; k++) {
|
||||
w2(5);
|
||||
w0(buf[k ^ 1]);
|
||||
w2(7);
|
||||
}
|
||||
w2(5); w2(4);
|
||||
break;
|
||||
case 2:
|
||||
w3(0x48); (void)r1();
|
||||
for (k = 0; k < count; k++)
|
||||
w4(buf[k ^ 1]);
|
||||
break;
|
||||
case 3:
|
||||
w3(0x48); (void)r1();
|
||||
for (k = 0; k < count / 2; k++)
|
||||
w4w(swab16(((u16 *)buf)[k]));
|
||||
break;
|
||||
|
||||
case 4: w3(0x48); (void)r1();
|
||||
break;
|
||||
case 4:
|
||||
w3(0x48); (void)r1();
|
||||
for (k = 0; k < count / 4; k++)
|
||||
w4l(swab16(((u16 *)buf)[2 * k]) |
|
||||
swab16(((u16 *)buf)[2 * k + 1]) << 16);
|
||||
break;
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void comm_log_adapter(struct pi_adapter *pi)
|
||||
|
||||
{ char *mode_string[5] = {"4-bit","8-bit","EPP-8","EPP-16","EPP-32"};
|
||||
{ char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
|
||||
|
||||
dev_info(&pi->dev, "DataStor Commuter at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
dev_info(&pi->dev,
|
||||
"DataStor Commuter at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
}
|
||||
|
||||
static struct pi_protocol comm = {
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/*
|
||||
dstr.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License.
|
||||
|
||||
dstr.c is a low-level protocol driver for the
|
||||
DataStor EP2000 parallel to IDE adapter chip.
|
||||
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* (c) 1997-1998 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* dstr.c is a low-level protocol driver for the DataStor EP2000 parallel
|
||||
* to IDE adapter chip.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -16,178 +15,202 @@
|
|||
#include <asm/io.h>
|
||||
#include "pata_parport.h"
|
||||
|
||||
/* mode codes: 0 nybble reads, 8-bit writes
|
||||
1 8-bit reads and writes
|
||||
2 8-bit EPP mode
|
||||
3 EPP-16
|
||||
4 EPP-32
|
||||
*/
|
||||
/*
|
||||
* mode codes: 0 nybble reads, 8-bit writes
|
||||
* 1 8-bit reads and writes
|
||||
* 2 8-bit EPP mode
|
||||
* 3 EPP-16
|
||||
* 4 EPP-32
|
||||
*/
|
||||
|
||||
#define j44(a,b) (((a>>3)&0x07)|((~a>>4)&0x08)|((b<<1)&0x70)|((~b)&0x80))
|
||||
#define j44(a, b) (((a >> 3) & 0x07) | ((~a >> 4) & 0x08) | \
|
||||
((b << 1) & 0x70) | ((~b) & 0x80))
|
||||
|
||||
#define P1 w2(5);w2(0xd);w2(5);w2(4);
|
||||
#define P2 w2(5);w2(7);w2(5);w2(4);
|
||||
#define P3 w2(6);w2(4);w2(6);w2(4);
|
||||
|
||||
/* cont = 0 - access the IDE register file
|
||||
cont = 1 - access the IDE command set
|
||||
*/
|
||||
|
||||
/*
|
||||
* cont = 0 - access the IDE register file
|
||||
* cont = 1 - access the IDE command set
|
||||
*/
|
||||
static int cont_map[2] = { 0x20, 0x40 };
|
||||
|
||||
static int dstr_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
{
|
||||
int a, b, r;
|
||||
|
||||
{ int a, b, r;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
r = regr + cont_map[cont];
|
||||
|
||||
w0(0x81); P1;
|
||||
if (pi->mode) { w0(0x11); } else { w0(1); }
|
||||
if (pi->mode)
|
||||
w0(0x11);
|
||||
else
|
||||
w0(1);
|
||||
P2; w0(r); P1;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4);
|
||||
return j44(a,b);
|
||||
|
||||
case 1: w0(0); w2(0x26); a = r0(); w2(4);
|
||||
return a;
|
||||
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4);
|
||||
return j44(a, b);
|
||||
case 1:
|
||||
w0(0); w2(0x26); a = r0(); w2(4);
|
||||
return a;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4: w2(0x24); a = r4(); w2(4);
|
||||
return a;
|
||||
case 4:
|
||||
w2(0x24); a = r4(); w2(4);
|
||||
return a;
|
||||
}
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void dstr_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
|
||||
{ int r;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
|
||||
w0(0x81); P1;
|
||||
if (pi->mode >= 2) { w0(0x11); } else { w0(1); }
|
||||
P2; w0(r); P1;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1: w0(val); w2(5); w2(7); w2(5); w2(4);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
case 4: w4(val);
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define CCP(x) w0(0xff);w2(0xc);w2(4);\
|
||||
w0(0xaa);w0(0x55);w0(0);w0(0xff);w0(0x87);w0(0x78);\
|
||||
w0(x);w2(5);w2(4);
|
||||
static void dstr_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
{
|
||||
int r = regr + cont_map[cont];
|
||||
|
||||
w0(0x81); P1;
|
||||
if (pi->mode >= 2)
|
||||
w0(0x11);
|
||||
else
|
||||
w0(1);
|
||||
P2; w0(r); P1;
|
||||
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
w0(val); w2(5); w2(7); w2(5); w2(4);
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
w4(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define CCP(x) \
|
||||
do { \
|
||||
w0(0xff); w2(0xc); w2(4); \
|
||||
w0(0xaa); w0(0x55); w0(0); w0(0xff); \
|
||||
w0(0x87); w0(0x78); \
|
||||
w0(x); w2(5); w2(4); \
|
||||
} while (0)
|
||||
|
||||
static void dstr_connect(struct pi_adapter *pi)
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(4); CCP(0xe0); w0(0xff);
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(4); CCP(0xe0); w0(0xff);
|
||||
}
|
||||
|
||||
static void dstr_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ CCP(0x30);
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
{
|
||||
CCP(0x30);
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
static void dstr_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int k, a, b;
|
||||
{
|
||||
int k, a, b;
|
||||
|
||||
w0(0x81); P1;
|
||||
if (pi->mode) { w0(0x19); } else { w0(9); }
|
||||
if (pi->mode)
|
||||
w0(0x19);
|
||||
else
|
||||
w0(9);
|
||||
P2; w0(0x82); P1; P3; w0(0x20); P1;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: for (k=0;k<count;k++) {
|
||||
w2(6); a = r1(); w2(4);
|
||||
w2(6); b = r1(); w2(4);
|
||||
buf[k] = j44(a,b);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: w0(0);
|
||||
for (k=0;k<count;k++) {
|
||||
w2(0x26); buf[k] = r0(); w2(0x24);
|
||||
}
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 2: w2(0x24);
|
||||
for (k=0;k<count;k++) buf[k] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 3: w2(0x24);
|
||||
for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 4: w2(0x24);
|
||||
for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
}
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
for (k = 0; k < count; k++) {
|
||||
w2(6); a = r1(); w2(4);
|
||||
w2(6); b = r1(); w2(4);
|
||||
buf[k] = j44(a, b);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
w0(0);
|
||||
for (k = 0; k < count; k++) {
|
||||
w2(0x26);
|
||||
buf[k] = r0();
|
||||
w2(0x24);
|
||||
}
|
||||
w2(4);
|
||||
break;
|
||||
case 2:
|
||||
w2(0x24);
|
||||
for (k = 0; k < count; k++)
|
||||
buf[k] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
case 3:
|
||||
w2(0x24);
|
||||
for (k = 0; k < count / 2; k++)
|
||||
((u16 *)buf)[k] = r4w();
|
||||
w2(4);
|
||||
break;
|
||||
case 4:
|
||||
w2(0x24);
|
||||
for (k = 0; k < count / 4; k++)
|
||||
((u32 *)buf)[k] = r4l();
|
||||
w2(4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void dstr_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int k;
|
||||
|
||||
{ int k;
|
||||
w0(0x81); P1;
|
||||
if (pi->mode)
|
||||
w0(0x19);
|
||||
else
|
||||
w0(9);
|
||||
P2; w0(0x82); P1; P3; w0(0x20); P1;
|
||||
|
||||
w0(0x81); P1;
|
||||
if (pi->mode) { w0(0x19); } else { w0(9); }
|
||||
P2; w0(0x82); P1; P3; w0(0x20); P1;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1: for (k=0;k<count;k++) {
|
||||
w2(5); w0(buf[k]); w2(7);
|
||||
}
|
||||
w2(5); w2(4);
|
||||
break;
|
||||
|
||||
case 2: w2(0xc5);
|
||||
for (k=0;k<count;k++) w4(buf[k]);
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
for (k = 0; k < count; k++) {
|
||||
w2(5);
|
||||
w0(buf[k]);
|
||||
w2(7);
|
||||
}
|
||||
w2(5); w2(4);
|
||||
break;
|
||||
case 2:
|
||||
w2(0xc5);
|
||||
for (k = 0; k < count; k++)
|
||||
w4(buf[k]);
|
||||
w2(0xc4);
|
||||
break;
|
||||
|
||||
case 3: w2(0xc5);
|
||||
for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
|
||||
w2(0xc4);
|
||||
break;
|
||||
|
||||
case 4: w2(0xc5);
|
||||
for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
|
||||
w2(0xc4);
|
||||
break;
|
||||
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
w2(0xc5);
|
||||
for (k = 0; k < count / 2; k++)
|
||||
w4w(((u16 *)buf)[k]);
|
||||
w2(0xc4);
|
||||
break;
|
||||
case 4:
|
||||
w2(0xc5);
|
||||
for (k = 0; k < count / 4; k++)
|
||||
w4l(((u32 *)buf)[k]);
|
||||
w2(0xc4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void dstr_log_adapter(struct pi_adapter *pi)
|
||||
|
||||
{ char *mode_string[5] = {"4-bit","8-bit","EPP-8",
|
||||
"EPP-16","EPP-32"};
|
||||
{
|
||||
char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
|
||||
|
||||
dev_info(&pi->dev, "DataStor EP2000 at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
dev_info(&pi->dev,
|
||||
"DataStor EP2000 at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
}
|
||||
|
||||
static struct pi_protocol dstr = {
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
/*
|
||||
epat.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License.
|
||||
|
||||
This is the low level protocol driver for the EPAT parallel
|
||||
to IDE adapter from Shuttle Technologies. This adapter is
|
||||
used in many popular parallel port disk products such as the
|
||||
SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk.
|
||||
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* (c) 1997-1998 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* This is the low level protocol driver for the EPAT parallel
|
||||
* to IDE adapter from Shuttle Technologies. This adapter is
|
||||
* used in many popular parallel port disk products such as the
|
||||
* SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -18,276 +17,313 @@
|
|||
#include <asm/io.h>
|
||||
#include "pata_parport.h"
|
||||
|
||||
#define j44(a,b) (((a>>4)&0x0f)+(b&0xf0))
|
||||
#define j53(a,b) (((a>>3)&0x1f)+((b<<4)&0xe0))
|
||||
#define j44(a, b) (((a >> 4) & 0x0f) + (b & 0xf0))
|
||||
#define j53(a, b) (((a >> 3) & 0x1f) + ((b << 4) & 0xe0))
|
||||
|
||||
static int epatc8;
|
||||
|
||||
module_param(epatc8, int, 0);
|
||||
MODULE_PARM_DESC(epatc8, "support for the Shuttle EP1284 chip, "
|
||||
"used in any recent Imation SuperDisk (LS-120) drive.");
|
||||
|
||||
/* cont = 0 IDE register file
|
||||
cont = 1 IDE control registers
|
||||
cont = 2 internal EPAT registers
|
||||
*/
|
||||
MODULE_PARM_DESC(epatc8,
|
||||
"support for the Shuttle EP1284 chip, "
|
||||
"used in any recent Imation SuperDisk (LS-120) drive.");
|
||||
|
||||
/*
|
||||
* cont = 0 IDE register file
|
||||
* cont = 1 IDE control registers
|
||||
* cont = 2 internal EPAT registers
|
||||
*/
|
||||
static int cont_map[3] = { 0x18, 0x10, 0 };
|
||||
|
||||
static void epat_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
{
|
||||
int r = regr + cont_map[cont];
|
||||
|
||||
{ int r;
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
w0(0x60+r); w2(1); w0(val); w2(4);
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
w3(0x40+r); w4(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int epat_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
{
|
||||
int a, b, r;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
case 2: w0(0x60+r); w2(1); w0(val); w2(4);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
case 5: w3(0x40+r); w4(val);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int epat_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
|
||||
{ int a, b, r;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w0(r); w2(1); w2(3);
|
||||
w0(r); w2(1); w2(3);
|
||||
a = r1(); w2(4); b = r1();
|
||||
return j44(a,b);
|
||||
|
||||
case 1: w0(0x40+r); w2(1); w2(4);
|
||||
return j44(a, b);
|
||||
case 1:
|
||||
w0(0x40+r); w2(1); w2(4);
|
||||
a = r1(); b = r2(); w0(0xff);
|
||||
return j53(a,b);
|
||||
|
||||
case 2: w0(0x20+r); w2(1); w2(0x25);
|
||||
return j53(a, b);
|
||||
case 2:
|
||||
w0(0x20+r); w2(1); w2(0x25);
|
||||
a = r0(); w2(4);
|
||||
return a;
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
case 5: w3(r); w2(0x24); a = r4(); w2(4);
|
||||
case 5:
|
||||
w3(r); w2(0x24); a = r4(); w2(4);
|
||||
return a;
|
||||
|
||||
}
|
||||
|
||||
return -1; /* never gets here */
|
||||
}
|
||||
|
||||
static void epat_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int k, ph, a, b;
|
||||
{
|
||||
int k, ph, a, b;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w0(7); w2(1); w2(3); w0(0xff);
|
||||
case 0:
|
||||
w0(7); w2(1); w2(3); w0(0xff);
|
||||
ph = 0;
|
||||
for(k=0;k<count;k++) {
|
||||
if (k == count-1) w0(0xfd);
|
||||
w2(6+ph); a = r1();
|
||||
if (a & 8) b = a;
|
||||
else { w2(4+ph); b = r1(); }
|
||||
buf[k] = j44(a,b);
|
||||
for (k = 0; k < count; k++) {
|
||||
if (k == count-1)
|
||||
w0(0xfd);
|
||||
w2(6 + ph); a = r1();
|
||||
if (a & 8) {
|
||||
b = a;
|
||||
} else {
|
||||
w2(4+ph); b = r1();
|
||||
}
|
||||
buf[k] = j44(a, b);
|
||||
ph = 1 - ph;
|
||||
}
|
||||
w0(0); w2(4);
|
||||
break;
|
||||
|
||||
case 1: w0(0x47); w2(1); w2(5); w0(0xff);
|
||||
case 1:
|
||||
w0(0x47); w2(1); w2(5); w0(0xff);
|
||||
ph = 0;
|
||||
for(k=0;k<count;k++) {
|
||||
if (k == count-1) w0(0xfd);
|
||||
w2(4+ph);
|
||||
for (k = 0; k < count; k++) {
|
||||
if (k == count - 1)
|
||||
w0(0xfd);
|
||||
w2(4 + ph);
|
||||
a = r1(); b = r2();
|
||||
buf[k] = j53(a,b);
|
||||
buf[k] = j53(a, b);
|
||||
ph = 1 - ph;
|
||||
}
|
||||
w0(0); w2(4);
|
||||
break;
|
||||
|
||||
case 2: w0(0x27); w2(1); w2(0x25); w0(0);
|
||||
case 2:
|
||||
w0(0x27); w2(1); w2(0x25); w0(0);
|
||||
ph = 0;
|
||||
for(k=0;k<count-1;k++) {
|
||||
w2(0x24+ph);
|
||||
for (k = 0; k < count - 1; k++) {
|
||||
w2(0x24 + ph);
|
||||
buf[k] = r0();
|
||||
ph = 1 - ph;
|
||||
}
|
||||
w2(0x26); w2(0x27); buf[count-1] = r0();
|
||||
w2(0x26); w2(0x27);
|
||||
buf[count - 1] = r0();
|
||||
w2(0x25); w2(4);
|
||||
break;
|
||||
|
||||
case 3: w3(0x80); w2(0x24);
|
||||
for(k=0;k<count-1;k++) buf[k] = r4();
|
||||
w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
|
||||
case 3:
|
||||
w3(0x80); w2(0x24);
|
||||
for (k = 0; k < count - 1; k++)
|
||||
buf[k] = r4();
|
||||
w2(4); w3(0xa0); w2(0x24);
|
||||
buf[count - 1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 4: w3(0x80); w2(0x24);
|
||||
for(k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
|
||||
buf[count-2] = r4();
|
||||
w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
|
||||
case 4:
|
||||
w3(0x80); w2(0x24);
|
||||
for (k = 0; k < count / 2 - 1; k++)
|
||||
((u16 *)buf)[k] = r4w();
|
||||
buf[count - 2] = r4();
|
||||
w2(4); w3(0xa0); w2(0x24);
|
||||
buf[count - 1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 5: w3(0x80); w2(0x24);
|
||||
for(k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
|
||||
for(k=count-4;k<count-1;k++) buf[k] = r4();
|
||||
w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
|
||||
case 5:
|
||||
w3(0x80); w2(0x24);
|
||||
for (k = 0; k < count / 4 - 1; k++)
|
||||
((u32 *)buf)[k] = r4l();
|
||||
for (k = count - 4; k < count - 1; k++)
|
||||
buf[k] = r4();
|
||||
w2(4); w3(0xa0); w2(0x24);
|
||||
buf[count - 1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void epat_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int ph, k;
|
||||
{
|
||||
int ph, k;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
case 2: w0(0x67); w2(1); w2(5);
|
||||
case 2:
|
||||
w0(0x67); w2(1); w2(5);
|
||||
ph = 0;
|
||||
for(k=0;k<count;k++) {
|
||||
for (k = 0; k < count; k++) {
|
||||
w0(buf[k]);
|
||||
w2(4+ph);
|
||||
w2(4 + ph);
|
||||
ph = 1 - ph;
|
||||
}
|
||||
w2(7); w2(4);
|
||||
break;
|
||||
|
||||
case 3: w3(0xc0);
|
||||
for(k=0;k<count;k++) w4(buf[k]);
|
||||
case 3:
|
||||
w3(0xc0);
|
||||
for (k = 0; k < count; k++)
|
||||
w4(buf[k]);
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 4: w3(0xc0);
|
||||
for(k=0;k<(count/2);k++) w4w(((u16 *)buf)[k]);
|
||||
case 4:
|
||||
w3(0xc0);
|
||||
for (k = 0; k < count / 2; k++)
|
||||
w4w(((u16 *)buf)[k]);
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 5: w3(0xc0);
|
||||
for(k=0;k<(count/4);k++) w4l(((u32 *)buf)[k]);
|
||||
case 5:
|
||||
w3(0xc0);
|
||||
for (k = 0; k < count / 4; k++)
|
||||
w4l(((u32 *)buf)[k]);
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* these macros access the EPAT registers in native addressing */
|
||||
|
||||
#define WR(r,v) epat_write_regr(pi,2,r,v)
|
||||
#define RR(r) (epat_read_regr(pi,2,r))
|
||||
#define WR(r, v) epat_write_regr(pi, 2, r, v)
|
||||
#define RR(r) epat_read_regr(pi, 2, r)
|
||||
|
||||
/* and these access the IDE task file */
|
||||
|
||||
#define WRi(r,v) epat_write_regr(pi,0,r,v)
|
||||
#define RRi(r) (epat_read_regr(pi,0,r))
|
||||
#define WRi(r, v) epat_write_regr(pi, 0, r, v)
|
||||
#define RRi(r) epat_read_regr(pi, 0, r)
|
||||
|
||||
/* FIXME: the CPP stuff should be fixed to handle multiple EPATs on a chain */
|
||||
|
||||
#define CPP(x) w2(4);w0(0x22);w0(0xaa);w0(0x55);w0(0);w0(0xff);\
|
||||
w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
|
||||
#define CPP(x) \
|
||||
do { \
|
||||
w2(4); w0(0x22); w0(0xaa); \
|
||||
w0(0x55); w0(0); w0(0xff); \
|
||||
w0(0x87); w0(0x78); w0(x); \
|
||||
w2(4); w2(5); w2(4); w0(0xff); \
|
||||
} while (0)
|
||||
|
||||
static void epat_connect(struct pi_adapter *pi)
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
|
||||
/* Initialize the chip */
|
||||
CPP(0);
|
||||
|
||||
if (epatc8) {
|
||||
CPP(0x40);CPP(0xe0);
|
||||
w0(0);w2(1);w2(4);
|
||||
WR(0x8,0x12);WR(0xc,0x14);WR(0x12,0x10);
|
||||
WR(0xe,0xf);WR(0xf,4);
|
||||
CPP(0x40); CPP(0xe0);
|
||||
w0(0); w2(1); w2(4);
|
||||
WR(0x8, 0x12);
|
||||
WR(0xc, 0x14);
|
||||
WR(0x12, 0x10);
|
||||
WR(0xe, 0xf);
|
||||
WR(0xf, 4);
|
||||
/* WR(0xe,0xa);WR(0xf,4); */
|
||||
WR(0xe,0xd);WR(0xf,0);
|
||||
WR(0xe, 0xd);
|
||||
WR(0xf, 0);
|
||||
/* CPP(0x30); */
|
||||
}
|
||||
|
||||
/* Connect to the chip */
|
||||
CPP(0xe0);
|
||||
w0(0);w2(1);w2(4); /* Idle into SPP */
|
||||
w0(0); w2(1); w2(4); /* Idle into SPP */
|
||||
if (pi->mode >= 3) {
|
||||
w0(0);w2(1);w2(4);w2(0xc);
|
||||
/* Request EPP */
|
||||
w0(0x40);w2(6);w2(7);w2(4);w2(0xc);w2(4);
|
||||
w0(0); w2(1); w2(4); w2(0xc);
|
||||
/* Request EPP */
|
||||
w0(0x40); w2(6); w2(7); w2(4); w2(0xc); w2(4);
|
||||
}
|
||||
|
||||
if (!epatc8) {
|
||||
WR(8,0x10); WR(0xc,0x14); WR(0xa,0x38); WR(0x12,0x10);
|
||||
WR(8, 0x10);
|
||||
WR(0xc, 0x14);
|
||||
WR(0xa, 0x38);
|
||||
WR(0x12, 0x10);
|
||||
}
|
||||
}
|
||||
|
||||
static void epat_disconnect(struct pi_adapter *pi)
|
||||
{ CPP(0x30);
|
||||
{
|
||||
CPP(0x30);
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
static int epat_test_proto(struct pi_adapter *pi)
|
||||
|
||||
{ int k, j, f, cc;
|
||||
int e[2] = {0,0};
|
||||
{
|
||||
int k, j, f, cc;
|
||||
int e[2] = { 0, 0 };
|
||||
char scratch[512];
|
||||
|
||||
epat_connect(pi);
|
||||
epat_connect(pi);
|
||||
cc = RR(0xd);
|
||||
epat_disconnect(pi);
|
||||
|
||||
epat_connect(pi);
|
||||
for (j=0;j<2;j++) {
|
||||
WRi(6,0xa0+j*0x10);
|
||||
for (k=0;k<256;k++) {
|
||||
WRi(2,k^0xaa);
|
||||
WRi(3,k^0x55);
|
||||
if (RRi(2) != (k^0xaa)) e[j]++;
|
||||
}
|
||||
}
|
||||
epat_disconnect(pi);
|
||||
WRi(6, 0xa0 + j * 0x10);
|
||||
for (k = 0; k < 256; k++) {
|
||||
WRi(2, k ^ 0xaa);
|
||||
WRi(3, k ^ 0x55);
|
||||
if (RRi(2) != (k ^ 0xaa))
|
||||
e[j]++;
|
||||
}
|
||||
}
|
||||
epat_disconnect(pi);
|
||||
|
||||
f = 0;
|
||||
epat_connect(pi);
|
||||
WR(0x13,1); WR(0x13,0); WR(0xa,0x11);
|
||||
epat_read_block(pi,scratch,512);
|
||||
|
||||
for (k=0;k<256;k++) {
|
||||
if ((scratch[2*k] & 0xff) != k) f++;
|
||||
if ((scratch[2*k+1] & 0xff) != (0xff-k)) f++;
|
||||
}
|
||||
epat_disconnect(pi);
|
||||
f = 0;
|
||||
epat_connect(pi);
|
||||
WR(0x13, 1); WR(0x13, 0); WR(0xa, 0x11);
|
||||
epat_read_block(pi, scratch, 512);
|
||||
|
||||
dev_dbg(&pi->dev, "epat: port 0x%x, mode %d, ccr %x, test=(%d,%d,%d)\n",
|
||||
pi->port, pi->mode, cc, e[0], e[1], f);
|
||||
|
||||
return (e[0] && e[1]) || f;
|
||||
for (k = 0; k < 256; k++) {
|
||||
if ((scratch[2 * k] & 0xff) != k)
|
||||
f++;
|
||||
if ((scratch[2 * k + 1] & 0xff) != 0xff - k)
|
||||
f++;
|
||||
}
|
||||
epat_disconnect(pi);
|
||||
|
||||
dev_dbg(&pi->dev,
|
||||
"epat: port 0x%x, mode %d, ccr %x, test=(%d,%d,%d)\n",
|
||||
pi->port, pi->mode, cc, e[0], e[1], f);
|
||||
|
||||
return (e[0] && e[1]) || f;
|
||||
}
|
||||
|
||||
static void epat_log_adapter(struct pi_adapter *pi)
|
||||
|
||||
{ int ver;
|
||||
char *mode_string[6] =
|
||||
{"4-bit","5/3","8-bit","EPP-8","EPP-16","EPP-32"};
|
||||
{
|
||||
int ver;
|
||||
char *mode_string[6] =
|
||||
{ "4-bit", "5/3", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
|
||||
|
||||
epat_connect(pi);
|
||||
WR(0xa,0x38); /* read the version code */
|
||||
ver = RR(0xb);
|
||||
epat_disconnect(pi);
|
||||
WR(0xa, 0x38); /* read the version code */
|
||||
ver = RR(0xb);
|
||||
epat_disconnect(pi);
|
||||
|
||||
dev_info(&pi->dev, "Shuttle EPAT chip %x at 0x%x, mode %d (%s), delay %d\n",
|
||||
dev_info(&pi->dev,
|
||||
"Shuttle EPAT chip %x at 0x%x, mode %d (%s), delay %d\n",
|
||||
ver, pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
/*
|
||||
epia.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License.
|
||||
|
||||
epia.c is a low-level protocol driver for Shuttle Technologies
|
||||
EPIA parallel to IDE adapter chip. This device is now obsolete
|
||||
and has been replaced with the EPAT chip, which is supported
|
||||
by epat.c, however, some devices based on EPIA are still
|
||||
available.
|
||||
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* (c) 1997-1998 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* epia.c is a low-level protocol driver for Shuttle Technologies
|
||||
* EPIA parallel to IDE adapter chip. This device is now obsolete
|
||||
* and has been replaced with the EPAT chip, which is supported
|
||||
* by epat.c, however, some devices based on EPIA are still
|
||||
* available.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -19,255 +18,274 @@
|
|||
#include <asm/io.h>
|
||||
#include "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
|
||||
2 8-bit reads and writes
|
||||
3 8-bit EPP mode
|
||||
4 16-bit EPP
|
||||
5 32-bit EPP
|
||||
*/
|
||||
/*
|
||||
* mode codes: 0 nybble reads on port 1, 8-bit writes
|
||||
* 1 5/3 reads on ports 1 & 2, 8-bit writes
|
||||
* 2 8-bit reads and writes
|
||||
* 3 8-bit EPP mode
|
||||
* 4 16-bit EPP
|
||||
* 5 32-bit EPP
|
||||
*/
|
||||
|
||||
#define j44(a,b) (((a>>4)&0x0f)+(b&0xf0))
|
||||
#define j53(a,b) (((a>>3)&0x1f)+((b<<4)&0xe0))
|
||||
|
||||
/* cont = 0 IDE register file
|
||||
cont = 1 IDE control registers
|
||||
*/
|
||||
#define j44(a, b) (((a >> 4) & 0x0f) + (b & 0xf0))
|
||||
#define j53(a, b) (((a >> 3) & 0x1f) + ((b << 4) & 0xe0))
|
||||
|
||||
/*
|
||||
* cont = 0 IDE register file
|
||||
* cont = 1 IDE control registers
|
||||
*/
|
||||
static int cont_map[2] = { 0, 0x80 };
|
||||
|
||||
static int epia_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
|
||||
{ int a, b, r;
|
||||
{
|
||||
int a, b, r;
|
||||
|
||||
regr += cont_map[cont];
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: r = regr^0x39;
|
||||
w0(r); w2(1); w2(3); w0(r);
|
||||
a = r1(); w2(1); b = r1(); w2(4);
|
||||
return j44(a,b);
|
||||
|
||||
case 1: r = regr^0x31;
|
||||
w0(r); w2(1); w0(r&0x37);
|
||||
w2(3); w2(5); w0(r|0xf0);
|
||||
a = r1(); b = r2(); w2(4);
|
||||
return j53(a,b);
|
||||
|
||||
case 2: r = regr^0x29;
|
||||
w0(r); w2(1); w2(0X21); w2(0x23);
|
||||
a = r0(); w2(4);
|
||||
return a;
|
||||
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
r = regr ^ 0x39;
|
||||
w0(r); w2(1); w2(3); w0(r);
|
||||
a = r1(); w2(1); b = r1(); w2(4);
|
||||
return j44(a, b);
|
||||
case 1:
|
||||
r = regr ^ 0x31;
|
||||
w0(r); w2(1); w0(r & 0x37);
|
||||
w2(3); w2(5); w0(r | 0xf0);
|
||||
a = r1(); b = r2(); w2(4);
|
||||
return j53(a, b);
|
||||
case 2:
|
||||
r = regr^0x29;
|
||||
w0(r); w2(1); w2(0X21); w2(0x23);
|
||||
a = r0(); w2(4);
|
||||
return a;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5: w3(regr); w2(0x24); a = r4(); w2(4);
|
||||
return a;
|
||||
case 5:
|
||||
w3(regr); w2(0x24); a = r4(); w2(4);
|
||||
return a;
|
||||
}
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void epia_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
|
||||
{ int r;
|
||||
|
||||
regr += cont_map[cont];
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
case 2: r = regr^0x19;
|
||||
w0(r); w2(1); w0(val); w2(3); w2(4);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
case 5: r = regr^0x40;
|
||||
w3(r); w4(val); w2(4);
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define WR(r,v) epia_write_regr(pi,0,r,v)
|
||||
#define RR(r) (epia_read_regr(pi,0,r))
|
||||
static void epia_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
{
|
||||
int r;
|
||||
|
||||
/* The use of register 0x84 is entirely unclear - it seems to control
|
||||
some EPP counters ... currently we know about 3 different block
|
||||
sizes: the standard 512 byte reads and writes, 12 byte writes and
|
||||
2048 byte reads (the last two being used in the CDrom drivers.
|
||||
*/
|
||||
regr += cont_map[cont];
|
||||
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
r = regr ^ 0x19;
|
||||
w0(r); w2(1); w0(val); w2(3); w2(4);
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
r = regr ^ 0x40;
|
||||
w3(r); w4(val); w2(4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define WR(r, v) epia_write_regr(pi, 0, r, v)
|
||||
#define RR(r) epia_read_regr(pi, 0, r)
|
||||
|
||||
/*
|
||||
* The use of register 0x84 is entirely unclear - it seems to control
|
||||
* some EPP counters ... currently we know about 3 different block
|
||||
* sizes: the standard 512 byte reads and writes, 12 byte writes and
|
||||
* 2048 byte reads (the last two being used in the CDrom drivers.
|
||||
*/
|
||||
static void epia_connect(struct pi_adapter *pi)
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
|
||||
w2(4); w0(0xa0); w0(0x50); w0(0xc0); w0(0x30); w0(0xa0); w0(0);
|
||||
w2(1); w2(4);
|
||||
if (pi->mode >= 3) {
|
||||
w0(0xa); w2(1); w2(4); w0(0x82); w2(4); w2(0xc); w2(4);
|
||||
w2(0x24); w2(0x26); w2(4);
|
||||
}
|
||||
WR(0x86,8);
|
||||
w2(4); w0(0xa0); w0(0x50); w0(0xc0); w0(0x30); w0(0xa0); w0(0);
|
||||
w2(1); w2(4);
|
||||
if (pi->mode >= 3) {
|
||||
w0(0xa); w2(1); w2(4); w0(0x82); w2(4); w2(0xc); w2(4);
|
||||
w2(0x24); w2(0x26); w2(4);
|
||||
}
|
||||
WR(0x86, 8);
|
||||
}
|
||||
|
||||
static void epia_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ /* WR(0x84,0x10); */
|
||||
w0(pi->saved_r0);
|
||||
w2(1); w2(4);
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
{
|
||||
/* WR(0x84,0x10); */
|
||||
w0(pi->saved_r0);
|
||||
w2(1); w2(4);
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
static void epia_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int k, ph, a, b;
|
||||
{
|
||||
int k, ph, a, b;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w0(0x81); w2(1); w2(3); w0(0xc1);
|
||||
ph = 1;
|
||||
for (k=0;k<count;k++) {
|
||||
w2(2+ph); a = r1();
|
||||
w2(4+ph); b = r1();
|
||||
buf[k] = j44(a,b);
|
||||
ph = 1 - ph;
|
||||
}
|
||||
w0(0); w2(4);
|
||||
break;
|
||||
|
||||
case 1: w0(0x91); w2(1); w0(0x10); w2(3);
|
||||
w0(0x51); w2(5); w0(0xd1);
|
||||
ph = 1;
|
||||
for (k=0;k<count;k++) {
|
||||
w2(4+ph);
|
||||
a = r1(); b = r2();
|
||||
buf[k] = j53(a,b);
|
||||
ph = 1 - ph;
|
||||
}
|
||||
w0(0); w2(4);
|
||||
break;
|
||||
|
||||
case 2: w0(0x89); w2(1); w2(0x23); w2(0x21);
|
||||
ph = 1;
|
||||
for (k=0;k<count;k++) {
|
||||
w2(0x24+ph);
|
||||
buf[k] = r0();
|
||||
ph = 1 - ph;
|
||||
}
|
||||
w2(6); w2(4);
|
||||
break;
|
||||
|
||||
case 3: if (count > 512) WR(0x84,3);
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
w0(0x81); w2(1); w2(3); w0(0xc1);
|
||||
ph = 1;
|
||||
for (k = 0; k < count; k++) {
|
||||
w2(2+ph); a = r1();
|
||||
w2(4+ph); b = r1();
|
||||
buf[k] = j44(a, b);
|
||||
ph = 1 - ph;
|
||||
}
|
||||
w0(0); w2(4);
|
||||
break;
|
||||
case 1:
|
||||
w0(0x91); w2(1); w0(0x10); w2(3);
|
||||
w0(0x51); w2(5); w0(0xd1);
|
||||
ph = 1;
|
||||
for (k = 0; k < count; k++) {
|
||||
w2(4 + ph);
|
||||
a = r1(); b = r2();
|
||||
buf[k] = j53(a, b);
|
||||
ph = 1 - ph;
|
||||
}
|
||||
w0(0); w2(4);
|
||||
break;
|
||||
case 2:
|
||||
w0(0x89); w2(1); w2(0x23); w2(0x21);
|
||||
ph = 1;
|
||||
for (k = 0; k < count; k++) {
|
||||
w2(0x24 + ph);
|
||||
buf[k] = r0();
|
||||
ph = 1 - ph;
|
||||
}
|
||||
w2(6); w2(4);
|
||||
break;
|
||||
case 3:
|
||||
if (count > 512)
|
||||
WR(0x84, 3);
|
||||
w3(0); w2(0x24);
|
||||
for (k=0;k<count;k++) buf[k] = r4();
|
||||
w2(4); WR(0x84,0);
|
||||
break;
|
||||
|
||||
case 4: if (count > 512) WR(0x84,3);
|
||||
for (k = 0; k < count; k++)
|
||||
buf[k] = r4();
|
||||
w2(4); WR(0x84, 0);
|
||||
break;
|
||||
case 4:
|
||||
if (count > 512)
|
||||
WR(0x84, 3);
|
||||
w3(0); w2(0x24);
|
||||
for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
|
||||
w2(4); WR(0x84,0);
|
||||
break;
|
||||
|
||||
case 5: if (count > 512) WR(0x84,3);
|
||||
for (k = 0; k < count / 2; k++)
|
||||
((u16 *)buf)[k] = r4w();
|
||||
w2(4); WR(0x84, 0);
|
||||
break;
|
||||
case 5:
|
||||
if (count > 512)
|
||||
WR(0x84, 3);
|
||||
w3(0); w2(0x24);
|
||||
for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
|
||||
w2(4); WR(0x84,0);
|
||||
break;
|
||||
|
||||
}
|
||||
for (k = 0; k < count / 4; k++)
|
||||
((u32 *)buf)[k] = r4l();
|
||||
w2(4); WR(0x84, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void epia_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int ph, k, last, d;
|
||||
|
||||
{ int ph, k, last, d;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
case 2: w0(0xa1); w2(1); w2(3); w2(1); w2(5);
|
||||
ph = 0; last = 0x8000;
|
||||
for (k=0;k<count;k++) {
|
||||
d = buf[k];
|
||||
if (d != last) { last = d; w0(d); }
|
||||
w2(4+ph);
|
||||
ph = 1 - ph;
|
||||
}
|
||||
w2(7); w2(4);
|
||||
break;
|
||||
|
||||
case 3: if (count < 512) WR(0x84,1);
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
w0(0xa1); w2(1); w2(3); w2(1); w2(5);
|
||||
ph = 0; last = 0x8000;
|
||||
for (k = 0; k < count; k++) {
|
||||
d = buf[k];
|
||||
if (d != last) {
|
||||
last = d;
|
||||
w0(d);
|
||||
}
|
||||
w2(4 + ph);
|
||||
ph = 1 - ph;
|
||||
}
|
||||
w2(7); w2(4);
|
||||
break;
|
||||
case 3:
|
||||
if (count < 512)
|
||||
WR(0x84, 1);
|
||||
w3(0x40);
|
||||
for (k=0;k<count;k++) w4(buf[k]);
|
||||
if (count < 512) WR(0x84,0);
|
||||
break;
|
||||
|
||||
case 4: if (count < 512) WR(0x84,1);
|
||||
for (k = 0; k < count; k++)
|
||||
w4(buf[k]);
|
||||
if (count < 512)
|
||||
WR(0x84, 0);
|
||||
break;
|
||||
case 4:
|
||||
if (count < 512)
|
||||
WR(0x84, 1);
|
||||
w3(0x40);
|
||||
for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
|
||||
if (count < 512) WR(0x84,0);
|
||||
break;
|
||||
|
||||
case 5: if (count < 512) WR(0x84,1);
|
||||
for (k = 0; k < count / 2; k++)
|
||||
w4w(((u16 *)buf)[k]);
|
||||
if (count < 512)
|
||||
WR(0x84, 0);
|
||||
break;
|
||||
case 5:
|
||||
if (count < 512)
|
||||
WR(0x84, 1);
|
||||
w3(0x40);
|
||||
for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
|
||||
if (count < 512) WR(0x84,0);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
for (k = 0; k < count / 4; k++)
|
||||
w4l(((u32 *)buf)[k]);
|
||||
if (count < 512)
|
||||
WR(0x84, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int epia_test_proto(struct pi_adapter *pi)
|
||||
|
||||
{ int j, k, f;
|
||||
int e[2] = {0,0};
|
||||
{
|
||||
int j, k, f;
|
||||
int e[2] = { 0, 0 };
|
||||
char scratch[512];
|
||||
|
||||
epia_connect(pi);
|
||||
for (j=0;j<2;j++) {
|
||||
WR(6,0xa0+j*0x10);
|
||||
for (k=0;k<256;k++) {
|
||||
WR(2,k^0xaa);
|
||||
WR(3,k^0x55);
|
||||
if (RR(2) != (k^0xaa)) e[j]++;
|
||||
}
|
||||
WR(2,1); WR(3,1);
|
||||
}
|
||||
epia_disconnect(pi);
|
||||
epia_connect(pi);
|
||||
for (j = 0; j < 2; j++) {
|
||||
WR(6, 0xa0 + j * 0x10);
|
||||
for (k = 0; k < 256; k++) {
|
||||
WR(2, k ^ 0xaa);
|
||||
WR(3, k ^ 0x55);
|
||||
if (RR(2) != (k ^ 0xaa))
|
||||
e[j]++;
|
||||
}
|
||||
WR(2, 1); WR(3, 1);
|
||||
}
|
||||
epia_disconnect(pi);
|
||||
|
||||
f = 0;
|
||||
epia_connect(pi);
|
||||
WR(0x84,8);
|
||||
epia_read_block(pi,scratch,512);
|
||||
for (k=0;k<256;k++) {
|
||||
if ((scratch[2*k] & 0xff) != ((k+1) & 0xff)) f++;
|
||||
if ((scratch[2*k+1] & 0xff) != ((-2-k) & 0xff)) f++;
|
||||
}
|
||||
WR(0x84,0);
|
||||
epia_disconnect(pi);
|
||||
f = 0;
|
||||
epia_connect(pi);
|
||||
WR(0x84, 8);
|
||||
epia_read_block(pi, scratch, 512);
|
||||
for (k = 0; k < 256; k++) {
|
||||
if ((scratch[2 * k] & 0xff) != ((k + 1) & 0xff))
|
||||
f++;
|
||||
if ((scratch[2 * k + 1] & 0xff) != ((-2 - k) & 0xff))
|
||||
f++;
|
||||
}
|
||||
WR(0x84, 0);
|
||||
epia_disconnect(pi);
|
||||
|
||||
dev_dbg(&pi->dev, "epia: port 0x%x, mode %d, test=(%d,%d,%d)\n",
|
||||
pi->port, pi->mode, e[0], e[1], f);
|
||||
|
||||
return (e[0] && e[1]) || f;
|
||||
pi->port, pi->mode, e[0], e[1], f);
|
||||
|
||||
return (e[0] && e[1]) || f;
|
||||
}
|
||||
|
||||
|
||||
static void epia_log_adapter(struct pi_adapter *pi)
|
||||
{
|
||||
char *mode[6] = { "4-bit", "5/3", "8-bit", "EPP-8", "EPP-16", "EPP-32"};
|
||||
|
||||
{ char *mode_string[6] = {"4-bit","5/3","8-bit",
|
||||
"EPP-8","EPP-16","EPP-32"};
|
||||
|
||||
dev_info(&pi->dev, "Shuttle EPIA at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
dev_info(&pi->dev,
|
||||
"Shuttle EPIA at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode[pi->mode], pi->delay);
|
||||
}
|
||||
|
||||
static struct pi_protocol epia = {
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
/*
|
||||
fit2.c (c) 1998 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License.
|
||||
|
||||
fit2.c is a low-level protocol driver for the older version
|
||||
of the Fidelity International Technology parallel port adapter.
|
||||
This adapter is used in their TransDisk 2000 and older TransDisk
|
||||
3000 portable hard-drives. As far as I can tell, this device
|
||||
supports 4-bit mode _only_.
|
||||
|
||||
Newer models of the FIT products use an enhanced protocol.
|
||||
The "fit3" protocol module should support current drives.
|
||||
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* (c) 1998 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* fit2.c is a low-level protocol driver for the older version
|
||||
* of the Fidelity International Technology parallel port adapter.
|
||||
* This adapter is used in their TransDisk 2000 and older TransDisk
|
||||
* 3000 portable hard-drives. As far as I can tell, this device
|
||||
* supports 4-bit mode _only_.
|
||||
*
|
||||
* Newer models of the FIT products use an enhanced protocol.
|
||||
* The "fit3" protocol module should support current drives.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -22,99 +21,97 @@
|
|||
#include <asm/io.h>
|
||||
#include "pata_parport.h"
|
||||
|
||||
#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0))
|
||||
#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0))
|
||||
|
||||
/* cont = 0 - access the IDE register file
|
||||
cont = 1 - access the IDE command set
|
||||
|
||||
NB: The FIT adapter does not appear to use the control registers.
|
||||
So, we map ALT_STATUS to STATUS and NO-OP writes to the device
|
||||
control register - this means that IDE reset will not work on these
|
||||
devices.
|
||||
|
||||
*/
|
||||
/*
|
||||
* cont = 0 - access the IDE register file
|
||||
* cont = 1 - access the IDE command set
|
||||
*
|
||||
* NB: The FIT adapter does not appear to use the control registers.
|
||||
* So, we map ALT_STATUS to STATUS and NO-OP writes to the device
|
||||
* control register - this means that IDE reset will not work on these
|
||||
* devices.
|
||||
*/
|
||||
|
||||
static void fit2_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
|
||||
{ if (cont == 1) return;
|
||||
{
|
||||
if (cont == 1)
|
||||
return;
|
||||
w2(0xc); w0(regr); w2(4); w0(val); w2(5); w0(0); w2(4);
|
||||
}
|
||||
|
||||
static int fit2_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
|
||||
{ int a, b, r;
|
||||
{
|
||||
int a, b, r;
|
||||
|
||||
if (cont) {
|
||||
if (regr != 6) return 0xff;
|
||||
r = 7;
|
||||
} else r = regr + 0x10;
|
||||
if (regr != 6)
|
||||
return 0xff;
|
||||
r = 7;
|
||||
} else {
|
||||
r = regr + 0x10;
|
||||
}
|
||||
|
||||
w2(0xc); w0(r); w2(4); w2(5);
|
||||
w0(0); a = r1();
|
||||
w0(1); b = r1();
|
||||
w2(0xc); w0(r); w2(4); w2(5);
|
||||
w0(0); a = r1();
|
||||
w0(1); b = r1();
|
||||
w2(4);
|
||||
|
||||
return j44(a,b);
|
||||
|
||||
return j44(a, b);
|
||||
}
|
||||
|
||||
static void fit2_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int k, a, b, c, d;
|
||||
{
|
||||
int k, a, b, c, d;
|
||||
|
||||
w2(0xc); w0(0x10);
|
||||
|
||||
for (k=0;k<count/4;k++) {
|
||||
|
||||
for (k = 0; k < count / 4; k++) {
|
||||
w2(4); w2(5);
|
||||
w0(0); a = r1(); w0(1); b = r1();
|
||||
w0(3); c = r1(); w0(2); d = r1();
|
||||
buf[4*k+0] = j44(a,b);
|
||||
buf[4*k+1] = j44(d,c);
|
||||
|
||||
w2(4); w2(5);
|
||||
a = r1(); w0(3); b = r1();
|
||||
w0(1); c = r1(); w0(0); d = r1();
|
||||
buf[4*k+2] = j44(d,c);
|
||||
buf[4*k+3] = j44(a,b);
|
||||
w0(3); c = r1(); w0(2); d = r1();
|
||||
buf[4 * k + 0] = j44(a, b);
|
||||
buf[4 * k + 1] = j44(d, c);
|
||||
|
||||
w2(4); w2(5);
|
||||
a = r1(); w0(3); b = r1();
|
||||
w0(1); c = r1(); w0(0); d = r1();
|
||||
buf[4 * k + 2] = j44(d, c);
|
||||
buf[4 * k + 3] = j44(a, b);
|
||||
}
|
||||
|
||||
w2(4);
|
||||
|
||||
}
|
||||
|
||||
static void fit2_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int k;
|
||||
|
||||
{ int k;
|
||||
|
||||
|
||||
w2(0xc); w0(0);
|
||||
for (k=0;k<count/2;k++) {
|
||||
w2(4); w0(buf[2*k]);
|
||||
w2(5); w0(buf[2*k+1]);
|
||||
w2(0xc); w0(0);
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w2(4); w0(buf[2 * k]);
|
||||
w2(5); w0(buf[2 * k + 1]);
|
||||
}
|
||||
w2(4);
|
||||
}
|
||||
|
||||
static void fit2_connect(struct pi_adapter *pi)
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(0xcc);
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(0xcc);
|
||||
}
|
||||
|
||||
static void fit2_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
{
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
static void fit2_log_adapter(struct pi_adapter *pi)
|
||||
|
||||
{
|
||||
dev_info(&pi->dev, "FIT 2000 adapter at 0x%x, delay %d\n",
|
||||
pi->port, pi->delay);
|
||||
pi->port, pi->delay);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
/*
|
||||
fit3.c (c) 1998 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License.
|
||||
|
||||
fit3.c is a low-level protocol driver for newer models
|
||||
of the Fidelity International Technology parallel port adapter.
|
||||
This adapter is used in their TransDisk 3000 portable
|
||||
hard-drives, as well as CD-ROM, PD-CD and other devices.
|
||||
|
||||
The TD-2000 and certain older devices use a different protocol.
|
||||
Try the fit2 protocol module with them.
|
||||
|
||||
NB: The FIT adapters do not appear to support the control
|
||||
registers. So, we map ALT_STATUS to STATUS and NO-OP writes
|
||||
to the device control register - this means that IDE reset
|
||||
will not work on these devices.
|
||||
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* (c) 1998 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* fit3.c is a low-level protocol driver for newer models
|
||||
* of the Fidelity International Technology parallel port adapter.
|
||||
* This adapter is used in their TransDisk 3000 portable
|
||||
* hard-drives, as well as CD-ROM, PD-CD and other devices.
|
||||
*
|
||||
* The TD-2000 and certain older devices use a different protocol.
|
||||
* Try the fit2 protocol module with them.
|
||||
*
|
||||
* NB: The FIT adapters do not appear to support the control
|
||||
* registers. So, we map ALT_STATUS to STATUS and NO-OP writes
|
||||
* to the device control register - this means that IDE reset
|
||||
* will not work on these devices.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -26,152 +25,155 @@
|
|||
#include <asm/io.h>
|
||||
#include "pata_parport.h"
|
||||
|
||||
#define j44(a,b) (((a>>3)&0x0f)|((b<<1)&0xf0))
|
||||
#define j44(a, b) (((a >> 3) & 0x0f) | ((b << 1) & 0xf0))
|
||||
|
||||
#define w7(byte) {out_p(7,byte);}
|
||||
#define r7() (in_p(7) & 0xff)
|
||||
#define w7(byte) out_p(7, byte)
|
||||
#define r7() (in_p(7) & 0xff)
|
||||
|
||||
/* cont = 0 - access the IDE register file
|
||||
cont = 1 - access the IDE command set
|
||||
|
||||
*/
|
||||
/*
|
||||
* cont = 0 - access the IDE register file
|
||||
* cont = 1 - access the IDE command set
|
||||
*/
|
||||
|
||||
static void fit3_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
|
||||
{ if (cont == 1) return;
|
||||
{
|
||||
if (cont == 1)
|
||||
return;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1: w2(0xc); w0(regr); w2(0x8); w2(0xc);
|
||||
w0(val); w2(0xd);
|
||||
case 1:
|
||||
w2(0xc); w0(regr); w2(0x8); w2(0xc);
|
||||
w0(val); w2(0xd);
|
||||
w0(0); w2(0xc);
|
||||
break;
|
||||
|
||||
case 2: w2(0xc); w0(regr); w2(0x8); w2(0xc);
|
||||
case 2:
|
||||
w2(0xc); w0(regr); w2(0x8); w2(0xc);
|
||||
w4(val); w4(0);
|
||||
w2(0xc);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int fit3_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
|
||||
{ int a, b;
|
||||
{
|
||||
int a, b;
|
||||
|
||||
if (cont) {
|
||||
if (regr != 6) return 0xff;
|
||||
regr = 7;
|
||||
}
|
||||
if (regr != 6)
|
||||
return 0xff;
|
||||
regr = 7;
|
||||
}
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc);
|
||||
case 0:
|
||||
w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc);
|
||||
w2(0xd); a = r1();
|
||||
w2(0xf); b = r1();
|
||||
w2(0xf); b = r1();
|
||||
w2(0xc);
|
||||
return j44(a,b);
|
||||
|
||||
case 1: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
|
||||
w2(0xec); w2(0xee); w2(0xef); a = r0();
|
||||
return j44(a, b);
|
||||
case 1:
|
||||
w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
|
||||
w2(0xec); w2(0xee); w2(0xef); a = r0();
|
||||
w2(0xc);
|
||||
return a;
|
||||
|
||||
case 2: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
|
||||
w2(0xec);
|
||||
a = r4(); b = r4();
|
||||
case 2:
|
||||
w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
|
||||
w2(0xec);
|
||||
a = r4(); b = r4();
|
||||
w2(0xc);
|
||||
return a;
|
||||
|
||||
}
|
||||
return -1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void fit3_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int k, a, b, c, d;
|
||||
{
|
||||
int k, a, b, c, d;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w2(0xc); w0(0x10); w2(0x8); w2(0xc);
|
||||
for (k=0;k<count/2;k++) {
|
||||
w2(0xd); a = r1();
|
||||
w2(0xf); b = r1();
|
||||
w2(0xc); c = r1();
|
||||
w2(0xe); d = r1();
|
||||
buf[2*k ] = j44(a,b);
|
||||
buf[2*k+1] = j44(c,d);
|
||||
case 0:
|
||||
w2(0xc); w0(0x10); w2(0x8); w2(0xc);
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w2(0xd); a = r1();
|
||||
w2(0xf); b = r1();
|
||||
w2(0xc); c = r1();
|
||||
w2(0xe); d = r1();
|
||||
buf[2 * k] = j44(a, b);
|
||||
buf[2 * k + 1] = j44(c, d);
|
||||
}
|
||||
w2(0xc);
|
||||
break;
|
||||
|
||||
case 1: w2(0xc); w0(0x90); w2(0x8); w2(0xc);
|
||||
case 1:
|
||||
w2(0xc); w0(0x90); w2(0x8); w2(0xc);
|
||||
w2(0xec); w2(0xee);
|
||||
for (k=0;k<count/2;k++) {
|
||||
w2(0xef); a = r0();
|
||||
w2(0xee); b = r0();
|
||||
buf[2*k ] = a;
|
||||
buf[2*k+1] = b;
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w2(0xef); a = r0();
|
||||
w2(0xee); b = r0();
|
||||
buf[2 * k] = a;
|
||||
buf[2 * k + 1] = b;
|
||||
}
|
||||
w2(0xec);
|
||||
w2(0xec);
|
||||
w2(0xc);
|
||||
break;
|
||||
|
||||
case 2: w2(0xc); w0(0x90); w2(0x8); w2(0xc);
|
||||
w2(0xec);
|
||||
for (k=0;k<count;k++) buf[k] = r4();
|
||||
w2(0xc);
|
||||
case 2:
|
||||
w2(0xc); w0(0x90); w2(0x8); w2(0xc);
|
||||
w2(0xec);
|
||||
for (k = 0; k < count; k++)
|
||||
buf[k] = r4();
|
||||
w2(0xc);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void fit3_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int k;
|
||||
|
||||
{ int k;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1: w2(0xc); w0(0); w2(0x8); w2(0xc);
|
||||
for (k=0;k<count/2;k++) {
|
||||
w0(buf[2*k ]); w2(0xd);
|
||||
w0(buf[2*k+1]); w2(0xc);
|
||||
case 1:
|
||||
w2(0xc); w0(0); w2(0x8); w2(0xc);
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w0(buf[2 * k]); w2(0xd);
|
||||
w0(buf[2 * k + 1]); w2(0xc);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: w2(0xc); w0(0); w2(0x8); w2(0xc);
|
||||
for (k=0;k<count;k++) w4(buf[k]);
|
||||
w2(0xc);
|
||||
case 2:
|
||||
w2(0xc); w0(0); w2(0x8); w2(0xc);
|
||||
for (k = 0; k < count; k++)
|
||||
w4(buf[k]);
|
||||
w2(0xc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void fit3_connect(struct pi_adapter *pi)
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(0xc); w0(0); w2(0xa);
|
||||
if (pi->mode == 2) {
|
||||
w2(0xc); w0(0x9); w2(0x8); w2(0xc);
|
||||
}
|
||||
if (pi->mode == 2) {
|
||||
w2(0xc); w0(0x9);
|
||||
w2(0x8); w2(0xc);
|
||||
}
|
||||
}
|
||||
|
||||
static void fit3_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ w2(0xc); w0(0xa); w2(0x8); w2(0xc);
|
||||
{
|
||||
w2(0xc); w0(0xa); w2(0x8); w2(0xc);
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
static void fit3_log_adapter(struct pi_adapter *pi)
|
||||
{
|
||||
char *mode_string[3] = { "4-bit", "8-bit", "EPP"};
|
||||
|
||||
{ char *mode_string[3] = {"4-bit","8-bit","EPP"};
|
||||
|
||||
dev_info(&pi->dev, "FIT 3000 adapter at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
dev_info(&pi->dev,
|
||||
"FIT 3000 adapter at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
}
|
||||
|
||||
static struct pi_protocol fit3 = {
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
/*
|
||||
friq.c (c) 1998 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License
|
||||
|
||||
friq.c is a low-level protocol driver for the Freecom "IQ"
|
||||
parallel port IDE adapter. Early versions of this adapter
|
||||
use the 'frpw' protocol.
|
||||
|
||||
Freecom uses this adapter in a battery powered external
|
||||
CD-ROM drive. It is also used in LS-120 drives by
|
||||
Maxell and Panasonic, and other devices.
|
||||
|
||||
The battery powered drive requires software support to
|
||||
control the power to the drive. This module enables the
|
||||
drive power when the high level driver (pcd) is loaded
|
||||
and disables it when the module is unloaded. Note, if
|
||||
the friq module is built in to the kernel, the power
|
||||
will never be switched off, so other means should be
|
||||
used to conserve battery power.
|
||||
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* (c) 1998 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* friq.c is a low-level protocol driver for the Freecom "IQ"
|
||||
* parallel port IDE adapter. Early versions of this adapter
|
||||
* use the 'frpw' protocol.
|
||||
*
|
||||
* Freecom uses this adapter in a battery powered external
|
||||
* CD-ROM drive. It is also used in LS-120 drives by
|
||||
* Maxell and Panasonic, and other devices.
|
||||
*
|
||||
* The battery powered drive requires software support to
|
||||
* control the power to the drive. This module enables the
|
||||
* drive power when the high level driver (pcd) is loaded
|
||||
* and disables it when the module is unloaded. Note, if
|
||||
* the friq module is built in to the kernel, the power
|
||||
* will never be switched off, so other means should be
|
||||
* used to conserve battery power.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -29,197 +28,206 @@
|
|||
#include <asm/io.h>
|
||||
#include "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);
|
||||
#define CMD(x) \
|
||||
do { \
|
||||
w2(4); w0(0xff); w0(0xff); w0(0x73); w0(0x73); \
|
||||
w0(0xc9); w0(0xc9); w0(0x26); \
|
||||
w0(0x26); w0(x); w0(x); \
|
||||
} while (0)
|
||||
|
||||
#define j44(l,h) (((l>>4)&0x0f)|(h&0xf0))
|
||||
#define j44(l, h) (((l >> 4) & 0x0f) | (h & 0xf0))
|
||||
|
||||
/* cont = 0 - access the IDE register file
|
||||
cont = 1 - access the IDE command set
|
||||
*/
|
||||
|
||||
static int cont_map[2] = { 0x08, 0x10 };
|
||||
/*
|
||||
* cont = 0 - access the IDE register file
|
||||
* cont = 1 - access the IDE command set
|
||||
*/
|
||||
static int cont_map[2] = { 0x08, 0x10 };
|
||||
|
||||
static int friq_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
|
||||
{ int h,l,r;
|
||||
{
|
||||
int h, l, r;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
|
||||
CMD(r);
|
||||
w2(6); l = r1();
|
||||
w2(4); h = r1();
|
||||
w2(4);
|
||||
|
||||
return j44(l,h);
|
||||
w2(4);
|
||||
|
||||
return j44(l, h);
|
||||
}
|
||||
|
||||
static void friq_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
|
||||
{ int r;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
{
|
||||
int r = regr + cont_map[cont];
|
||||
|
||||
CMD(r);
|
||||
w0(val);
|
||||
w2(5);w2(7);w2(5);w2(4);
|
||||
w2(5); w2(7); w2(5); w2(4);
|
||||
}
|
||||
|
||||
static void friq_read_block_int(struct pi_adapter *pi, char *buf, int count, int regr)
|
||||
{
|
||||
int h, l, k, ph;
|
||||
|
||||
{ int h, l, k, ph;
|
||||
|
||||
switch(pi->mode) {
|
||||
|
||||
case 0: CMD(regr);
|
||||
for (k=0;k<count;k++) {
|
||||
w2(6); l = r1();
|
||||
w2(4); h = r1();
|
||||
buf[k] = j44(l,h);
|
||||
}
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 1: ph = 2;
|
||||
CMD(regr+0xc0);
|
||||
w0(0xff);
|
||||
for (k=0;k<count;k++) {
|
||||
w2(0xa4 + ph);
|
||||
buf[k] = r0();
|
||||
ph = 2 - ph;
|
||||
}
|
||||
w2(0xac); w2(0xa4); w2(4);
|
||||
break;
|
||||
|
||||
case 2: CMD(regr+0x80);
|
||||
for (k=0;k<count-2;k++) buf[k] = r4();
|
||||
w2(0xac); w2(0xa4);
|
||||
buf[count-2] = r4();
|
||||
buf[count-1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 3: CMD(regr+0x80);
|
||||
for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
|
||||
w2(0xac); w2(0xa4);
|
||||
buf[count-2] = r4();
|
||||
buf[count-1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 4: CMD(regr+0x80);
|
||||
for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
|
||||
buf[count-4] = r4();
|
||||
buf[count-3] = r4();
|
||||
w2(0xac); w2(0xa4);
|
||||
buf[count-2] = r4();
|
||||
buf[count-1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void friq_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ friq_read_block_int(pi,buf,count,0x08);
|
||||
}
|
||||
|
||||
static void friq_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int k;
|
||||
|
||||
switch(pi->mode) {
|
||||
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1: CMD(8); w2(5);
|
||||
for (k=0;k<count;k++) {
|
||||
w0(buf[k]);
|
||||
w2(7);w2(5);
|
||||
CMD(regr);
|
||||
for (k = 0; k < count; k++) {
|
||||
w2(6); l = r1();
|
||||
w2(4); h = r1();
|
||||
buf[k] = j44(l, h);
|
||||
}
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 2: CMD(0xc8); w2(5);
|
||||
for (k=0;k<count;k++) w4(buf[k]);
|
||||
case 1:
|
||||
ph = 2;
|
||||
CMD(regr + 0xc0);
|
||||
w0(0xff);
|
||||
for (k = 0; k < count; k++) {
|
||||
w2(0xa4 + ph);
|
||||
buf[k] = r0();
|
||||
ph = 2 - ph;
|
||||
}
|
||||
w2(0xac); w2(0xa4); w2(4);
|
||||
break;
|
||||
case 2:
|
||||
CMD(regr + 0x80);
|
||||
for (k = 0; k < count - 2; k++)
|
||||
buf[k] = r4();
|
||||
w2(0xac); w2(0xa4);
|
||||
buf[count - 2] = r4();
|
||||
buf[count - 1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
case 3:
|
||||
CMD(regr + 0x80);
|
||||
for (k = 0; k < count / 2 - 1; k++)
|
||||
((u16 *)buf)[k] = r4w();
|
||||
w2(0xac); w2(0xa4);
|
||||
buf[count - 2] = r4();
|
||||
buf[count - 1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
case 4:
|
||||
CMD(regr + 0x80);
|
||||
for (k = 0; k < count / 4 - 1; k++)
|
||||
((u32 *)buf)[k] = r4l();
|
||||
buf[count - 4] = r4();
|
||||
buf[count - 3] = r4();
|
||||
w2(0xac); w2(0xa4);
|
||||
buf[count - 2] = r4();
|
||||
buf[count - 1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 3: CMD(0xc8); w2(5);
|
||||
for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 4: CMD(0xc8); w2(5);
|
||||
for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
|
||||
w2(4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void friq_connect(struct pi_adapter *pi)
|
||||
static void friq_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
friq_read_block_int(pi, buf, count, 0x08);
|
||||
}
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
static void friq_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int k;
|
||||
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
CMD(8); w2(5);
|
||||
for (k = 0; k < count; k++) {
|
||||
w0(buf[k]);
|
||||
w2(7); w2(5);
|
||||
}
|
||||
w2(4);
|
||||
break;
|
||||
case 2:
|
||||
CMD(0xc8); w2(5);
|
||||
for (k = 0; k < count; k++)
|
||||
w4(buf[k]);
|
||||
w2(4);
|
||||
break;
|
||||
case 3:
|
||||
CMD(0xc8); w2(5);
|
||||
for (k = 0; k < count / 2; k++)
|
||||
w4w(((u16 *)buf)[k]);
|
||||
w2(4);
|
||||
break;
|
||||
case 4:
|
||||
CMD(0xc8); w2(5);
|
||||
for (k = 0; k < count / 4; k++)
|
||||
w4l(((u32 *)buf)[k]);
|
||||
w2(4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void friq_connect(struct pi_adapter *pi)
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(4);
|
||||
}
|
||||
|
||||
static void friq_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ CMD(0x20);
|
||||
{
|
||||
CMD(0x20);
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
static int friq_test_proto(struct pi_adapter *pi)
|
||||
|
||||
{ int j, k, r;
|
||||
int e[2] = {0,0};
|
||||
{
|
||||
int j, k, r;
|
||||
int e[2] = { 0, 0 };
|
||||
char scratch[512];
|
||||
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r0 = r0();
|
||||
w0(0xff); udelay(20); CMD(0x3d); /* turn the power on */
|
||||
udelay(500);
|
||||
w0(pi->saved_r0);
|
||||
|
||||
friq_connect(pi);
|
||||
for (j=0;j<2;j++) {
|
||||
friq_write_regr(pi,0,6,0xa0+j*0x10);
|
||||
for (k=0;k<256;k++) {
|
||||
friq_write_regr(pi,0,2,k^0xaa);
|
||||
friq_write_regr(pi,0,3,k^0x55);
|
||||
if (friq_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
|
||||
}
|
||||
}
|
||||
for (j = 0; j < 2; j++) {
|
||||
friq_write_regr(pi, 0, 6, 0xa0 + j * 0x10);
|
||||
for (k = 0; k < 256; k++) {
|
||||
friq_write_regr(pi, 0, 2, k ^ 0xaa);
|
||||
friq_write_regr(pi, 0, 3, k ^ 0x55);
|
||||
if (friq_read_regr(pi, 0, 2) != (k ^ 0xaa))
|
||||
e[j]++;
|
||||
}
|
||||
}
|
||||
friq_disconnect(pi);
|
||||
|
||||
friq_connect(pi);
|
||||
friq_read_block_int(pi,scratch,512,0x10);
|
||||
r = 0;
|
||||
for (k=0;k<128;k++) if (scratch[k] != k) r++;
|
||||
friq_read_block_int(pi, scratch, 512, 0x10);
|
||||
r = 0;
|
||||
for (k = 0; k < 128; k++) {
|
||||
if (scratch[k] != k)
|
||||
r++;
|
||||
}
|
||||
friq_disconnect(pi);
|
||||
|
||||
dev_dbg(&pi->dev, "friq: port 0x%x, mode %d, test=(%d,%d,%d)\n",
|
||||
pi->port, pi->mode, e[0], e[1], r);
|
||||
dev_dbg(&pi->dev,
|
||||
"friq: port 0x%x, mode %d, test=(%d,%d,%d)\n",
|
||||
pi->port, pi->mode, e[0], e[1], r);
|
||||
|
||||
return (r || (e[0] && e[1]));
|
||||
return r || (e[0] && e[1]);
|
||||
}
|
||||
|
||||
|
||||
static void friq_log_adapter(struct pi_adapter *pi)
|
||||
{
|
||||
char *mode_string[6] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32"};
|
||||
|
||||
{ char *mode_string[6] = {"4-bit","8-bit",
|
||||
"EPP-8","EPP-16","EPP-32"};
|
||||
|
||||
dev_info(&pi->dev, "Freecom IQ ASIC-2 adapter at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
dev_info(&pi->dev,
|
||||
"Freecom IQ ASIC-2 adapter at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
|
||||
pi->private = 1;
|
||||
friq_connect(pi);
|
||||
CMD(0x9e); /* disable sleep timer */
|
||||
friq_disconnect(pi);
|
||||
|
||||
}
|
||||
|
||||
static void friq_release_proto(struct pi_adapter *pi)
|
||||
|
|
|
@ -1,17 +1,15 @@
|
|||
/*
|
||||
frpw.c (c) 1996-8 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License
|
||||
|
||||
frpw.c is a low-level protocol driver for the Freecom "Power"
|
||||
parallel port IDE adapter.
|
||||
|
||||
Some applications of this adapter may require a "printer" reset
|
||||
prior to loading the driver. This can be done by loading and
|
||||
unloading the "lp" driver, or it can be done by this driver
|
||||
if you define FRPW_HARD_RESET. The latter is not recommended
|
||||
as it may upset devices on other ports.
|
||||
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* (c) 1996-1998 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* frpw.c is a low-level protocol driver for the Freecom "Power" parallel port
|
||||
* IDE adapter.
|
||||
*
|
||||
* Some applications of this adapter may require a "printer" reset prior to
|
||||
* loading the driver. This can be done by loading and unloading the "lp"
|
||||
* driver, or it can be done by this driver if you define FRPW_HARD_RESET.
|
||||
* The latter is not recommended as it may upset devices on other ports.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -25,15 +23,15 @@
|
|||
#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))
|
||||
|
||||
/* cont = 0 - access the IDE register file
|
||||
cont = 1 - access the IDE command set
|
||||
*/
|
||||
|
||||
/*
|
||||
* cont = 0 - access the IDE register file
|
||||
* cont = 1 - access the IDE command set
|
||||
*/
|
||||
static int cont_map[2] = { 0x08, 0x10 };
|
||||
|
||||
static int frpw_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
|
||||
{ int h,l,r;
|
||||
{
|
||||
int h, l, r;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
|
||||
|
@ -41,145 +39,156 @@ static int frpw_read_regr(struct pi_adapter *pi, int cont, int regr)
|
|||
w0(r); cec4;
|
||||
w2(6); l = r1();
|
||||
w2(4); h = r1();
|
||||
w2(4);
|
||||
|
||||
return j44(l,h);
|
||||
w2(4);
|
||||
|
||||
return j44(l, h);
|
||||
}
|
||||
|
||||
static void frpw_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
{
|
||||
int r = regr + cont_map[cont];
|
||||
|
||||
{ int r;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
|
||||
w2(4); w0(r); cec4;
|
||||
w2(4); w0(r); cec4;
|
||||
w0(val);
|
||||
w2(5);w2(7);w2(5);w2(4);
|
||||
w2(5); w2(7); w2(5); w2(4);
|
||||
}
|
||||
|
||||
static void frpw_read_block_int(struct pi_adapter *pi, char *buf, int count, int regr)
|
||||
|
||||
{ int h, l, k, ph;
|
||||
|
||||
switch(pi->mode) {
|
||||
|
||||
case 0: w2(4); w0(regr); cec4;
|
||||
for (k=0;k<count;k++) {
|
||||
w2(6); l = r1();
|
||||
w2(4); h = r1();
|
||||
buf[k] = j44(l,h);
|
||||
}
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 1: ph = 2;
|
||||
w2(4); w0(regr + 0xc0); cec4;
|
||||
w0(0xff);
|
||||
for (k=0;k<count;k++) {
|
||||
w2(0xa4 + ph);
|
||||
buf[k] = r0();
|
||||
ph = 2 - ph;
|
||||
}
|
||||
w2(0xac); w2(0xa4); w2(4);
|
||||
break;
|
||||
|
||||
case 2: w2(4); w0(regr + 0x80); cec4;
|
||||
for (k=0;k<count;k++) buf[k] = r4();
|
||||
w2(0xac); w2(0xa4);
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 3: w2(4); w0(regr + 0x80); cec4;
|
||||
for (k=0;k<count-2;k++) buf[k] = r4();
|
||||
w2(0xac); w2(0xa4);
|
||||
buf[count-2] = r4();
|
||||
buf[count-1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 4: w2(4); w0(regr + 0x80); cec4;
|
||||
for (k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
|
||||
w2(0xac); w2(0xa4);
|
||||
buf[count-2] = r4();
|
||||
buf[count-1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 5: w2(4); w0(regr + 0x80); cec4;
|
||||
for (k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
|
||||
buf[count-4] = r4();
|
||||
buf[count-3] = r4();
|
||||
w2(0xac); w2(0xa4);
|
||||
buf[count-2] = r4();
|
||||
buf[count-1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void frpw_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ frpw_read_block_int(pi,buf,count,0x08);
|
||||
}
|
||||
|
||||
static void frpw_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int k;
|
||||
|
||||
switch(pi->mode) {
|
||||
static void frpw_read_block_int(struct pi_adapter *pi, char *buf, int count,
|
||||
int regr)
|
||||
{
|
||||
int h, l, k, ph;
|
||||
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2: w2(4); w0(8); cec4; w2(5);
|
||||
for (k=0;k<count;k++) {
|
||||
w0(buf[k]);
|
||||
w2(7);w2(5);
|
||||
w2(4); w0(regr); cec4;
|
||||
for (k = 0; k < count; k++) {
|
||||
w2(6); l = r1();
|
||||
w2(4); h = r1();
|
||||
buf[k] = j44(l, h);
|
||||
}
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 3: w2(4); w0(0xc8); cec4; w2(5);
|
||||
for (k=0;k<count;k++) w4(buf[k]);
|
||||
case 1:
|
||||
ph = 2;
|
||||
w2(4); w0(regr + 0xc0); cec4;
|
||||
w0(0xff);
|
||||
for (k = 0; k < count; k++) {
|
||||
w2(0xa4 + ph);
|
||||
buf[k] = r0();
|
||||
ph = 2 - ph;
|
||||
}
|
||||
w2(0xac); w2(0xa4); w2(4);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
w2(4); w0(regr + 0x80); cec4;
|
||||
for (k = 0; k < count; k++)
|
||||
buf[k] = r4();
|
||||
w2(0xac); w2(0xa4);
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 4: w2(4); w0(0xc8); cec4; w2(5);
|
||||
for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
|
||||
w2(4);
|
||||
break;
|
||||
case 3:
|
||||
w2(4); w0(regr + 0x80); cec4;
|
||||
for (k = 0; k < count - 2; k++)
|
||||
buf[k] = r4();
|
||||
w2(0xac); w2(0xa4);
|
||||
buf[count - 2] = r4();
|
||||
buf[count - 1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 5: w2(4); w0(0xc8); cec4; w2(5);
|
||||
for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
|
||||
w2(4);
|
||||
break;
|
||||
case 4:
|
||||
w2(4); w0(regr + 0x80); cec4;
|
||||
for (k = 0; k < count / 2 - 1; k++)
|
||||
((u16 *)buf)[k] = r4w();
|
||||
w2(0xac); w2(0xa4);
|
||||
buf[count - 2] = r4();
|
||||
buf[count - 1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
w2(4); w0(regr + 0x80); cec4;
|
||||
for (k = 0; k < count / 4 - 1; k++)
|
||||
((u32 *)buf)[k] = r4l();
|
||||
buf[count - 4] = r4();
|
||||
buf[count - 3] = r4();
|
||||
w2(0xac); w2(0xa4);
|
||||
buf[count - 2] = r4();
|
||||
buf[count - 1] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void frpw_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
frpw_read_block_int(pi, buf, count, 0x08);
|
||||
}
|
||||
|
||||
static void frpw_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int k;
|
||||
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
w2(4); w0(8); cec4; w2(5);
|
||||
for (k = 0; k < count; k++) {
|
||||
w0(buf[k]);
|
||||
w2(7); w2(5);
|
||||
}
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
w2(4); w0(0xc8); cec4; w2(5);
|
||||
for (k = 0; k < count; k++)
|
||||
w4(buf[k]);
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
w2(4); w0(0xc8); cec4; w2(5);
|
||||
for (k = 0; k < count / 2; k++)
|
||||
w4w(((u16 *)buf)[k]);
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
w2(4); w0(0xc8); cec4; w2(5);
|
||||
for (k = 0; k < count / 4; k++)
|
||||
w4l(((u32 *)buf)[k]);
|
||||
w2(4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void frpw_connect(struct pi_adapter *pi)
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(4);
|
||||
}
|
||||
|
||||
static void frpw_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ w2(4); w0(0x20); cec4;
|
||||
{
|
||||
w2(4); w0(0x20); cec4;
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
/* Stub logic to see if PNP string is available - used to distinguish
|
||||
between the Xilinx and ASIC implementations of the Freecom adapter.
|
||||
*/
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Stub logic to see if PNP string is available - used to distinguish
|
||||
* between the Xilinx and ASIC implementations of the Freecom adapter.
|
||||
* returns chip_type: 0 = Xilinx, 1 = ASIC
|
||||
*/
|
||||
static int frpw_test_pnp(struct pi_adapter *pi)
|
||||
|
||||
/* returns chip_type: 0 = Xilinx, 1 = ASIC */
|
||||
|
||||
{ int olddelay, a, b;
|
||||
{
|
||||
int olddelay, a, b;
|
||||
|
||||
#ifdef FRPW_HARD_RESET
|
||||
w0(0); w2(8); udelay(50); w2(0xc); /* parallel bus reset */
|
||||
|
@ -191,7 +200,7 @@ static int frpw_test_pnp(struct pi_adapter *pi)
|
|||
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
|
||||
|
||||
w2(4); w0(4); w2(6); w2(7);
|
||||
a = r1() & 0xff; w2(4); b = r1() & 0xff;
|
||||
w2(0xc); w2(0xe); w2(4);
|
||||
|
@ -200,65 +209,70 @@ static int frpw_test_pnp(struct pi_adapter *pi)
|
|||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
|
||||
return ((~a&0x40) && (b&0x40));
|
||||
}
|
||||
|
||||
/* We use the pi->private to remember the result of the PNP test.
|
||||
To make this work, private = port*2 + chip. Yes, I know it's
|
||||
a hack :-(
|
||||
*/
|
||||
|
||||
static int frpw_test_proto(struct pi_adapter *pi)
|
||||
|
||||
{ int j, k, r;
|
||||
int e[2] = {0,0};
|
||||
char scratch[512];
|
||||
|
||||
if ((pi->private>>1) != pi->port)
|
||||
pi->private = frpw_test_pnp(pi) + 2*pi->port;
|
||||
|
||||
if (((pi->private%2) == 0) && (pi->mode > 2)) {
|
||||
dev_dbg(&pi->dev, "frpw: Xilinx does not support mode %d\n", pi->mode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (((pi->private%2) == 1) && (pi->mode == 2)) {
|
||||
dev_dbg(&pi->dev, "frpw: ASIC does not support mode 2\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
frpw_connect(pi);
|
||||
for (j=0;j<2;j++) {
|
||||
frpw_write_regr(pi,0,6,0xa0+j*0x10);
|
||||
for (k=0;k<256;k++) {
|
||||
frpw_write_regr(pi,0,2,k^0xaa);
|
||||
frpw_write_regr(pi,0,3,k^0x55);
|
||||
if (frpw_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
|
||||
}
|
||||
}
|
||||
frpw_disconnect(pi);
|
||||
|
||||
frpw_connect(pi);
|
||||
frpw_read_block_int(pi,scratch,512,0x10);
|
||||
r = 0;
|
||||
for (k=0;k<128;k++) if (scratch[k] != k) r++;
|
||||
frpw_disconnect(pi);
|
||||
|
||||
dev_dbg(&pi->dev, "frpw: port 0x%x, chip %ld, mode %d, test=(%d,%d,%d)\n",
|
||||
pi->port, (pi->private%2), pi->mode, e[0], e[1], r);
|
||||
|
||||
return (r || (e[0] && e[1]));
|
||||
return ((~a & 0x40) && (b & 0x40));
|
||||
}
|
||||
|
||||
/*
|
||||
* We use the pi->private to remember the result of the PNP test.
|
||||
* To make this work, private = port*2 + chip. Yes, I know it's a hack :-(
|
||||
*/
|
||||
static int frpw_test_proto(struct pi_adapter *pi)
|
||||
{
|
||||
int j, k, r;
|
||||
int e[2] = { 0, 0 };
|
||||
char scratch[512];
|
||||
|
||||
if ((pi->private >> 1) != pi->port)
|
||||
pi->private = frpw_test_pnp(pi) + 2*pi->port;
|
||||
|
||||
if (((pi->private & 0x1) == 0) && (pi->mode > 2)) {
|
||||
dev_dbg(&pi->dev,
|
||||
"frpw: Xilinx does not support mode %d\n", pi->mode);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (((pi->private & 0x1) == 1) && (pi->mode == 2)) {
|
||||
dev_dbg(&pi->dev, "frpw: ASIC does not support mode 2\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
frpw_connect(pi);
|
||||
for (j = 0; j < 2; j++) {
|
||||
frpw_write_regr(pi, 0, 6, 0xa0 + j * 0x10);
|
||||
for (k = 0; k < 256; k++) {
|
||||
frpw_write_regr(pi, 0, 2, k ^ 0xaa);
|
||||
frpw_write_regr(pi, 0, 3, k ^ 0x55);
|
||||
if (frpw_read_regr(pi, 0, 2) != (k ^ 0xaa))
|
||||
e[j]++;
|
||||
}
|
||||
}
|
||||
frpw_disconnect(pi);
|
||||
|
||||
frpw_connect(pi);
|
||||
frpw_read_block_int(pi, scratch, 512, 0x10);
|
||||
r = 0;
|
||||
for (k = 0; k < 128; k++) {
|
||||
if (scratch[k] != k)
|
||||
r++;
|
||||
}
|
||||
frpw_disconnect(pi);
|
||||
|
||||
dev_dbg(&pi->dev,
|
||||
"frpw: port 0x%x, chip %ld, mode %d, test=(%d,%d,%d)\n",
|
||||
pi->port, (pi->private%2), pi->mode, e[0], e[1], r);
|
||||
|
||||
return r || (e[0] && e[1]);
|
||||
}
|
||||
|
||||
static void frpw_log_adapter(struct pi_adapter *pi)
|
||||
|
||||
{ char *mode_string[6] = {"4-bit","8-bit","EPP",
|
||||
"EPP-8","EPP-16","EPP-32"};
|
||||
{
|
||||
char *mode[6] = { "4-bit", "8-bit", "EPP", "EPP-8", "EPP-16", "EPP-32"};
|
||||
|
||||
dev_info(&pi->dev, "Freecom (%s) adapter at 0x%x, mode %d (%s), delay %d\n",
|
||||
((pi->private % 2) == 0) ? "Xilinx" : "ASIC",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
dev_info(&pi->dev,
|
||||
"Freecom (%s) adapter at 0x%x, mode %d (%s), delay %d\n",
|
||||
((pi->private & 0x1) == 0) ? "Xilinx" : "ASIC",
|
||||
pi->port, pi->mode, mode[pi->mode], pi->delay);
|
||||
}
|
||||
|
||||
static struct pi_protocol frpw = {
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
kbic.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License.
|
||||
|
||||
This is a low-level driver for the KBIC-951A and KBIC-971A
|
||||
parallel to IDE adapter chips from KingByte Information Systems.
|
||||
|
||||
The chips are almost identical, however, the wakeup code
|
||||
required for the 971A interferes with the correct operation of
|
||||
the 951A, so this driver registers itself twice, once for
|
||||
each chip.
|
||||
|
||||
*/
|
||||
* (c) 1997-1998 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* This is a low-level driver for the KBIC-951A and KBIC-971A
|
||||
* parallel to IDE adapter chips from KingByte Information Systems.
|
||||
*
|
||||
* The chips are almost identical, however, the wakeup code
|
||||
* required for the 971A interferes with the correct operation of
|
||||
* the 951A, so this driver registers itself twice, once for
|
||||
* each chip.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -21,212 +20,223 @@
|
|||
#include <asm/io.h>
|
||||
#include "pata_parport.h"
|
||||
|
||||
#define r12w() (delay_p,inw(pi->port+1)&0xffff)
|
||||
#define r12w() (delay_p, inw(pi->port + 1) & 0xffff)
|
||||
|
||||
#define j44(a,b) ((((a>>4)&0x0f)|(b&0xf0))^0x88)
|
||||
#define j53(w) (((w>>3)&0x1f)|((w>>4)&0xe0))
|
||||
#define j44(a, b) ((((a >> 4) & 0x0f) | (b & 0xf0)) ^ 0x88)
|
||||
#define j53(w) (((w >> 3) & 0x1f) | ((w >> 4) & 0xe0))
|
||||
|
||||
|
||||
/* cont = 0 - access the IDE register file
|
||||
cont = 1 - access the IDE command set
|
||||
*/
|
||||
|
||||
static int cont_map[2] = { 0x80, 0x40 };
|
||||
/*
|
||||
* cont = 0 - access the IDE register file
|
||||
* cont = 1 - access the IDE command set
|
||||
*/
|
||||
static int cont_map[2] = { 0x80, 0x40 };
|
||||
|
||||
static int kbic_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
{
|
||||
int a, b, s;
|
||||
|
||||
{ int a, b, s;
|
||||
|
||||
s = cont_map[cont];
|
||||
s = cont_map[cont];
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w0(regr|0x18|s); w2(4); w2(6); w2(4); w2(1); w0(8);
|
||||
a = r1(); w0(0x28); b = r1(); w2(4);
|
||||
return j44(a,b);
|
||||
|
||||
case 1: w0(regr|0x38|s); w2(4); w2(6); w2(4); w2(5); w0(8);
|
||||
case 0:
|
||||
w0(regr | 0x18 | s); w2(4); w2(6); w2(4); w2(1); w0(8);
|
||||
a = r1(); w0(0x28); b = r1(); w2(4);
|
||||
return j44(a, b);
|
||||
case 1:
|
||||
w0(regr|0x38 | s); w2(4); w2(6); w2(4); w2(5); w0(8);
|
||||
a = r12w(); w2(4);
|
||||
return j53(a);
|
||||
|
||||
case 2: w0(regr|0x08|s); w2(4); w2(6); w2(4); w2(0xa5); w2(0xa1);
|
||||
case 2:
|
||||
w0(regr | 0x08 | s); w2(4); w2(6); w2(4); w2(0xa5); w2(0xa1);
|
||||
a = r0(); w2(4);
|
||||
return a;
|
||||
|
||||
return a;
|
||||
case 3:
|
||||
case 4:
|
||||
case 5: w0(0x20|s); w2(4); w2(6); w2(4); w3(regr);
|
||||
case 5:
|
||||
w0(0x20 | s); w2(4); w2(6); w2(4); w3(regr);
|
||||
a = r4(); b = r4(); w2(4); w2(0); w2(4);
|
||||
return a;
|
||||
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void kbic_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
{
|
||||
int s = cont_map[cont];
|
||||
|
||||
{ int s;
|
||||
|
||||
s = cont_map[cont];
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
case 2: w0(regr|0x10|s); w2(4); w2(6); w2(4);
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
w0(regr | 0x10 | s); w2(4); w2(6); w2(4);
|
||||
w0(val); w2(5); w2(4);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
case 4:
|
||||
case 5: w0(0x20|s); w2(4); w2(6); w2(4); w3(regr);
|
||||
case 5:
|
||||
w0(0x20 | s); w2(4); w2(6); w2(4); w3(regr);
|
||||
w4(val); w4(val);
|
||||
w2(4); w2(0); w2(4);
|
||||
break;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void k951_connect(struct pi_adapter *pi)
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(4);
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(4);
|
||||
}
|
||||
|
||||
static void k951_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
{
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
#define CCP(x) w2(0xc4);w0(0xaa);w0(0x55);w0(0);w0(0xff);w0(0x87);\
|
||||
w0(0x78);w0(x);w2(0xc5);w2(0xc4);w0(0xff);
|
||||
#define CCP(x) \
|
||||
do { \
|
||||
w2(0xc4); w0(0xaa); w0(0x55); \
|
||||
w0(0); w0(0xff); w0(0x87); \
|
||||
w0(0x78); w0(x); w2(0xc5); \
|
||||
w2(0xc4); w0(0xff); \
|
||||
} while (0)
|
||||
|
||||
static void k971_connect(struct pi_adapter *pi)
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
CCP(0x20);
|
||||
w2(4);
|
||||
w2(4);
|
||||
}
|
||||
|
||||
static void k971_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ CCP(0x30);
|
||||
{
|
||||
CCP(0x30);
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
/* counts must be congruent to 0 MOD 4, but all known applications
|
||||
have this property.
|
||||
*/
|
||||
|
||||
/*
|
||||
* count must be congruent to 0 MOD 4, but all known applications
|
||||
*have this property.
|
||||
*/
|
||||
static void kbic_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int k, a, b;
|
||||
|
||||
{ int k, a, b;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w0(0x98); w2(4); w2(6); w2(4);
|
||||
for (k=0;k<count/2;k++) {
|
||||
w2(1); w0(8); a = r1();
|
||||
w0(0x28); b = r1();
|
||||
buf[2*k] = j44(a,b);
|
||||
w2(5); b = r1();
|
||||
w0(8); a = r1();
|
||||
buf[2*k+1] = j44(a,b);
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
w0(0x98); w2(4); w2(6); w2(4);
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w2(1); w0(8);
|
||||
a = r1();
|
||||
w0(0x28);
|
||||
b = r1();
|
||||
buf[2 * k] = j44(a, b);
|
||||
w2(5);
|
||||
b = r1();
|
||||
w0(8);
|
||||
a = r1();
|
||||
buf[2 * k + 1] = j44(a, b);
|
||||
w2(4);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: w0(0xb8); w2(4); w2(6); w2(4);
|
||||
for (k=0;k<count/4;k++) {
|
||||
w0(0xb8);
|
||||
w2(4); w2(5);
|
||||
w0(8); buf[4*k] = j53(r12w());
|
||||
w0(0xb8); buf[4*k+1] = j53(r12w());
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
w0(0xb8); w2(4); w2(6); w2(4);
|
||||
for (k = 0; k < count / 4; k++) {
|
||||
w0(0xb8);
|
||||
w2(4); w2(5);
|
||||
buf[4*k+3] = j53(r12w());
|
||||
w0(8); buf[4*k+2] = j53(r12w());
|
||||
}
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 2: w0(0x88); w2(4); w2(6); w2(4);
|
||||
for (k=0;k<count/2;k++) {
|
||||
w2(0xa0); w2(0xa1); buf[2*k] = r0();
|
||||
w2(0xa5); buf[2*k+1] = r0();
|
||||
}
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 3: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||
for (k=0;k<count;k++) buf[k] = r4();
|
||||
w2(4); w2(0); w2(4);
|
||||
break;
|
||||
|
||||
case 4: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||
for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
|
||||
w2(4); w2(0); w2(4);
|
||||
break;
|
||||
|
||||
case 5: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||
for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
|
||||
w2(4); w2(0); w2(4);
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
w0(8);
|
||||
buf[4 * k] = j53(r12w());
|
||||
w0(0xb8);
|
||||
buf[4 * k + 1] = j53(r12w());
|
||||
w2(4); w2(5);
|
||||
buf[4 * k + 3] = j53(r12w());
|
||||
w0(8);
|
||||
buf[4 * k + 2] = j53(r12w());
|
||||
}
|
||||
w2(4);
|
||||
break;
|
||||
case 2:
|
||||
w0(0x88); w2(4); w2(6); w2(4);
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w2(0xa0); w2(0xa1);
|
||||
buf[2 * k] = r0();
|
||||
w2(0xa5);
|
||||
buf[2 * k + 1] = r0();
|
||||
}
|
||||
w2(4);
|
||||
break;
|
||||
case 3:
|
||||
w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||
for (k = 0; k < count; k++)
|
||||
buf[k] = r4();
|
||||
w2(4); w2(0); w2(4);
|
||||
break;
|
||||
case 4:
|
||||
w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||
for (k = 0; k < count / 2; k++)
|
||||
((u16 *)buf)[k] = r4w();
|
||||
w2(4); w2(0); w2(4);
|
||||
break;
|
||||
case 5:
|
||||
w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||
for (k = 0; k < count / 4; k++)
|
||||
((u32 *)buf)[k] = r4l();
|
||||
w2(4); w2(0); w2(4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void kbic_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int k;
|
||||
|
||||
{ int k;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1:
|
||||
case 2: w0(0x90); w2(4); w2(6); w2(4);
|
||||
for(k=0;k<count/2;k++) {
|
||||
w0(buf[2*k+1]); w2(0); w2(4);
|
||||
w0(buf[2*k]); w2(5); w2(4);
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
w0(0x90); w2(4); w2(6); w2(4);
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w0(buf[2 * k + 1]);
|
||||
w2(0); w2(4);
|
||||
w0(buf[2 * k]);
|
||||
w2(5); w2(4);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||
for(k=0;k<count/2;k++) {
|
||||
w4(buf[2*k+1]);
|
||||
w4(buf[2*k]);
|
||||
}
|
||||
case 3:
|
||||
w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w4(buf[2 * k + 1]);
|
||||
w4(buf[2 * k]);
|
||||
}
|
||||
w2(4); w2(0); w2(4);
|
||||
break;
|
||||
|
||||
case 4: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||
case 4:
|
||||
w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||
for (k = 0; k < count / 2; k++)
|
||||
w4w(swab16(((u16 *)buf)[k]));
|
||||
w2(4); w2(0); w2(4);
|
||||
break;
|
||||
|
||||
case 5: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||
w2(4); w2(0); w2(4);
|
||||
break;
|
||||
case 5:
|
||||
w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||
for (k = 0; k < count / 4; k++)
|
||||
w4l(swab16(((u16 *)buf)[2 * k]) |
|
||||
swab16(((u16 *)buf)[2 * k + 1]) << 16);
|
||||
w2(4); w2(0); w2(4);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
w2(4); w2(0); w2(4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void kbic_log_adapter(struct pi_adapter *pi, char *chip)
|
||||
|
||||
{ char *mode_string[6] = {"4-bit","5/3","8-bit",
|
||||
"EPP-8","EPP_16","EPP-32"};
|
||||
{
|
||||
char *mode[6] = { "4-bit", "5/3", "8-bit", "EPP-8", "EPP_16", "EPP-32"};
|
||||
|
||||
dev_info(&pi->dev, "KingByte %s at 0x%x, mode %d (%s), delay %d\n",
|
||||
chip, pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
chip, pi->port, pi->mode, mode[pi->mode], pi->delay);
|
||||
}
|
||||
|
||||
static void k951_log_adapter(struct pi_adapter *pi)
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
/*
|
||||
ktti.c (c) 1998 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License.
|
||||
|
||||
ktti.c is a low-level protocol driver for the KT Technology
|
||||
parallel port adapter. This adapter is used in the "PHd"
|
||||
portable hard-drives. As far as I can tell, this device
|
||||
supports 4-bit mode _only_.
|
||||
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* (c) 1998 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* ktti.c is a low-level protocol driver for the KT Technology
|
||||
* parallel port adapter. This adapter is used in the "PHd"
|
||||
* portable hard-drives. As far as I can tell, this device
|
||||
* supports 4-bit mode _only_.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -18,80 +17,76 @@
|
|||
#include <asm/io.h>
|
||||
#include "pata_parport.h"
|
||||
|
||||
#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0))
|
||||
#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0))
|
||||
|
||||
/* cont = 0 - access the IDE register file
|
||||
cont = 1 - access the IDE command set
|
||||
*/
|
||||
|
||||
static int cont_map[2] = { 0x10, 0x08 };
|
||||
/*
|
||||
* cont = 0 - access the IDE register file
|
||||
* cont = 1 - access the IDE command set
|
||||
*/
|
||||
static int cont_map[2] = { 0x10, 0x08 };
|
||||
|
||||
static void ktti_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
{
|
||||
int r = regr + cont_map[cont];
|
||||
|
||||
{ int r;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
|
||||
w0(r); w2(0xb); w2(0xa); w2(3); w2(6);
|
||||
w0(r); w2(0xb); w2(0xa); w2(3); w2(6);
|
||||
w0(val); w2(3); w0(0); w2(6); w2(0xb);
|
||||
}
|
||||
|
||||
static int ktti_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
|
||||
{ int a, b, r;
|
||||
{
|
||||
int a, b, r;
|
||||
|
||||
r = regr + cont_map[cont];
|
||||
|
||||
w0(r); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9);
|
||||
w0(r); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9);
|
||||
a = r1(); w2(0xc); b = r1(); w2(9); w2(0xc); w2(9);
|
||||
return j44(a,b);
|
||||
|
||||
return j44(a, b);
|
||||
}
|
||||
|
||||
static void ktti_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int k, a, b;
|
||||
|
||||
{ int k, a, b;
|
||||
|
||||
for (k=0;k<count/2;k++) {
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w0(0x10); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9);
|
||||
a = r1(); w2(0xc); b = r1(); w2(9);
|
||||
buf[2*k] = j44(a,b);
|
||||
buf[2*k] = j44(a, b);
|
||||
a = r1(); w2(0xc); b = r1(); w2(9);
|
||||
buf[2*k+1] = j44(a,b);
|
||||
buf[2*k+1] = j44(a, b);
|
||||
}
|
||||
}
|
||||
|
||||
static void ktti_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int k;
|
||||
|
||||
{ int k;
|
||||
|
||||
for (k=0;k<count/2;k++) {
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w0(0x10); w2(0xb); w2(0xa); w2(3); w2(6);
|
||||
w0(buf[2*k]); w2(3);
|
||||
w0(buf[2*k+1]); w2(6);
|
||||
w0(buf[2 * k]); w2(3);
|
||||
w0(buf[2 * k + 1]); w2(6);
|
||||
w2(0xb);
|
||||
}
|
||||
}
|
||||
|
||||
static void ktti_connect(struct pi_adapter *pi)
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(0xb); w2(0xa); w0(0); w2(3); w2(6);
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
w2(0xb); w2(0xa); w0(0); w2(3); w2(6);
|
||||
}
|
||||
|
||||
static void ktti_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ w2(0xb); w2(0xa); w0(0xa0); w2(3); w2(4);
|
||||
{
|
||||
w2(0xb); w2(0xa); w0(0xa0); w2(3); w2(4);
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
static void ktti_log_adapter(struct pi_adapter *pi)
|
||||
|
||||
{
|
||||
dev_info(&pi->dev, "KT adapter at 0x%x, delay %d\n",
|
||||
pi->port, pi->delay);
|
||||
pi->port, pi->delay);
|
||||
}
|
||||
|
||||
static struct pi_protocol ktti = {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
on20.c (c) 1996-8 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License.
|
||||
|
||||
on20.c is a low-level protocol driver for the
|
||||
Onspec 90c20 parallel to IDE adapter.
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* (c) 1996-1998 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* on20.c is a low-level protocol driver for the
|
||||
* Onspec 90c20 parallel to IDE adapter.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -15,99 +15,114 @@
|
|||
#include <asm/io.h>
|
||||
#include "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);
|
||||
#define op(f) \
|
||||
do { \
|
||||
w2(4); w0(f); w2(5); w2(0xd); \
|
||||
w2(5); w2(0xd); w2(5); w2(4); \
|
||||
} while (0)
|
||||
|
||||
#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0))
|
||||
#define vl(v) \
|
||||
do { \
|
||||
w2(4); w0(v); w2(5); \
|
||||
w2(7); w2(5); w2(4); \
|
||||
} while (0)
|
||||
|
||||
/* cont = 0 - access the IDE register file
|
||||
cont = 1 - access the IDE command set
|
||||
*/
|
||||
#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0))
|
||||
|
||||
/*
|
||||
* cont = 0 - access the IDE register file
|
||||
* cont = 1 - access the IDE command set
|
||||
*/
|
||||
|
||||
static int on20_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
{
|
||||
int h, l, r;
|
||||
|
||||
{ int h,l, r ;
|
||||
r = (regr << 2) + 1 + cont;
|
||||
|
||||
r = (regr<<2) + 1 + cont;
|
||||
|
||||
op(1); vl(r); op(0);
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w2(4); w2(6); l = r1();
|
||||
w2(4); w2(6); h = r1();
|
||||
w2(4); w2(6); w2(4); w2(6); w2(4);
|
||||
return j44(l,h);
|
||||
|
||||
case 1: w2(4); w2(0x26); r = r0();
|
||||
w2(4); w2(0x26); w2(4);
|
||||
return r;
|
||||
op(1); vl(r); op(0);
|
||||
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
w2(4); w2(6); l = r1();
|
||||
w2(4); w2(6); h = r1();
|
||||
w2(4); w2(6); w2(4); w2(6); w2(4);
|
||||
return j44(l, h);
|
||||
case 1:
|
||||
w2(4); w2(0x26); r = r0();
|
||||
w2(4); w2(0x26); w2(4);
|
||||
return r;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static void on20_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
{
|
||||
int r = (regr << 2) + 1 + cont;
|
||||
|
||||
{ int r;
|
||||
|
||||
r = (regr<<2) + 1 + cont;
|
||||
|
||||
op(1); vl(r);
|
||||
op(0); vl(val);
|
||||
op(1); vl(r);
|
||||
op(0); vl(val);
|
||||
op(0); vl(val);
|
||||
}
|
||||
|
||||
static void on20_connect(struct pi_adapter *pi)
|
||||
{
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
|
||||
{ pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
|
||||
w2(4);w0(0);w2(0xc);w2(4);w2(6);w2(4);w2(6);w2(4);
|
||||
if (pi->mode) { op(2); vl(8); op(2); vl(9); }
|
||||
else { op(2); vl(0); op(2); vl(8); }
|
||||
w2(4); w0(0); w2(0xc); w2(4); w2(6); w2(4); w2(6); w2(4);
|
||||
if (pi->mode) {
|
||||
op(2); vl(8); op(2); vl(9);
|
||||
} else {
|
||||
op(2); vl(0); op(2); vl(8);
|
||||
}
|
||||
}
|
||||
|
||||
static void on20_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ w2(4);w0(7);w2(4);w2(0xc);w2(4);
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
{
|
||||
w2(4); w0(7); w2(4); w2(0xc); w2(4);
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
static void on20_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int k, l, h;
|
||||
{
|
||||
int k, l, h;
|
||||
|
||||
op(1); vl(1); op(0);
|
||||
|
||||
for (k=0;k<count;k++)
|
||||
if (pi->mode) {
|
||||
w2(4); w2(0x26); buf[k] = r0();
|
||||
} else {
|
||||
w2(6); l = r1(); w2(4);
|
||||
w2(6); h = r1(); w2(4);
|
||||
buf[k] = j44(l,h);
|
||||
}
|
||||
for (k = 0; k < count; k++) {
|
||||
if (pi->mode) {
|
||||
w2(4); w2(0x26); buf[k] = r0();
|
||||
} else {
|
||||
w2(6); l = r1(); w2(4);
|
||||
w2(6); h = r1(); w2(4);
|
||||
buf[k] = j44(l, h);
|
||||
}
|
||||
}
|
||||
w2(4);
|
||||
}
|
||||
|
||||
static void on20_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
|
||||
{ int k;
|
||||
{
|
||||
int k;
|
||||
|
||||
op(1); vl(1); op(0);
|
||||
|
||||
for (k=0;k<count;k++) { w2(5); w0(buf[k]); w2(7); }
|
||||
for (k = 0; k < count; k++) {
|
||||
w2(5); w0(buf[k]); w2(7);
|
||||
}
|
||||
w2(4);
|
||||
}
|
||||
|
||||
static void on20_log_adapter(struct pi_adapter *pi)
|
||||
{
|
||||
char *mode_string[2] = { "4-bit", "8-bit" };
|
||||
|
||||
{ char *mode_string[2] = {"4-bit","8-bit"};
|
||||
|
||||
dev_info(&pi->dev, "OnSpec 90c20 at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
dev_info(&pi->dev,
|
||||
"OnSpec 90c20 at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
}
|
||||
|
||||
static struct pi_protocol on20 = {
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
/*
|
||||
on26.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
||||
Under the terms of the GNU General Public License.
|
||||
|
||||
on26.c is a low-level protocol driver for the
|
||||
OnSpec 90c26 parallel to IDE adapter chip.
|
||||
|
||||
*/
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* (c) 1997-1998 Grant R. Guenther <grant@torque.net>
|
||||
*
|
||||
* on26.c is a low-level protocol driver for the
|
||||
* OnSpec 90c26 parallel to IDE adapter chip.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
|
@ -16,260 +15,281 @@
|
|||
#include <asm/io.h>
|
||||
#include "pata_parport.h"
|
||||
|
||||
/* mode codes: 0 nybble reads, 8-bit writes
|
||||
1 8-bit reads and writes
|
||||
2 8-bit EPP mode
|
||||
3 EPP-16
|
||||
4 EPP-32
|
||||
*/
|
||||
/*
|
||||
* mode codes: 0 nybble reads, 8-bit writes
|
||||
* 1 8-bit reads and writes
|
||||
* 2 8-bit EPP mode
|
||||
* 3 EPP-16
|
||||
* 4 EPP-32
|
||||
*/
|
||||
|
||||
#define j44(a,b) (((a>>4)&0x0f)|(b&0xf0))
|
||||
#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0))
|
||||
|
||||
#define P1 w2(5);w2(0xd);w2(5);w2(0xd);w2(5);w2(4);
|
||||
#define P2 w2(5);w2(7);w2(5);w2(4);
|
||||
#define P1 \
|
||||
do { \
|
||||
w2(5); w2(0xd); w2(5); w2(0xd); w2(5); w2(4); \
|
||||
} while (0)
|
||||
|
||||
/* cont = 0 - access the IDE register file
|
||||
cont = 1 - access the IDE command set
|
||||
*/
|
||||
#define P2 \
|
||||
do { \
|
||||
w2(5); w2(7); w2(5); w2(4); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* cont = 0 - access the IDE register file
|
||||
* cont = 1 - access the IDE command set
|
||||
*/
|
||||
|
||||
static int on26_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||
{
|
||||
int a, b, r;
|
||||
|
||||
{ int a, b, r;
|
||||
r = (regr << 2) + 1 + cont;
|
||||
|
||||
r = (regr<<2) + 1 + cont;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w0(1); P1; w0(r); P2; w0(0); P1;
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
w0(1); P1; w0(r); P2; w0(0); P1;
|
||||
w2(6); a = r1(); w2(4);
|
||||
w2(6); b = r1(); w2(4);
|
||||
w2(6); w2(4); w2(6); w2(4);
|
||||
return j44(a,b);
|
||||
|
||||
case 1: w0(1); P1; w0(r); P2; w0(0); P1;
|
||||
return j44(a, b);
|
||||
case 1:
|
||||
w0(1); P1; w0(r); P2; w0(0); P1;
|
||||
w2(0x26); a = r0(); w2(4); w2(0x26); w2(4);
|
||||
return a;
|
||||
|
||||
return a;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4: w3(1); w3(1); w2(5); w4(r); w2(4);
|
||||
case 4:
|
||||
w3(1); w3(1); w2(5); w4(r); w2(4);
|
||||
w3(0); w3(0); w2(0x24); a = r4(); w2(4);
|
||||
w2(0x24); (void)r4(); w2(4);
|
||||
return a;
|
||||
return a;
|
||||
}
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void on26_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
|
||||
{ int r;
|
||||
|
||||
r = (regr<<2) + 1 + cont;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1: w0(1); P1; w0(r); P2; w0(0); P1;
|
||||
w0(val); P2; w0(val); P2;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
case 3:
|
||||
case 4: w3(1); w3(1); w2(5); w4(r); w2(4);
|
||||
w3(0); w3(0);
|
||||
w2(5); w4(val); w2(4);
|
||||
w2(5); w4(val); w2(4);
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define CCP(x) w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);\
|
||||
w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
|
||||
static void on26_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||
{
|
||||
int r = (regr << 2) + 1 + cont;
|
||||
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
w0(1); P1; w0(r); P2; w0(0); P1;
|
||||
w0(val); P2; w0(val); P2;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
w3(1); w3(1); w2(5); w4(r); w2(4);
|
||||
w3(0); w3(0);
|
||||
w2(5); w4(val); w2(4);
|
||||
w2(5); w4(val); w2(4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define CCP(x) \
|
||||
do { \
|
||||
w0(0xfe); w0(0xaa); w0(0x55); w0(0); \
|
||||
w0(0xff); w0(0x87); w0(0x78); w0(x); \
|
||||
w2(4); w2(5); w2(4); w0(0xff); \
|
||||
} while (0)
|
||||
|
||||
static void on26_connect(struct pi_adapter *pi)
|
||||
|
||||
{ int x;
|
||||
{
|
||||
int x;
|
||||
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
pi->saved_r2 = r2();
|
||||
|
||||
CCP(0x20);
|
||||
x = 8; if (pi->mode) x = 9;
|
||||
CCP(0x20);
|
||||
if (pi->mode)
|
||||
x = 9;
|
||||
else
|
||||
x = 8;
|
||||
|
||||
w0(2); P1; w0(8); P2;
|
||||
w0(2); P1; w0(x); P2;
|
||||
}
|
||||
|
||||
static void on26_disconnect(struct pi_adapter *pi)
|
||||
|
||||
{ if (pi->mode >= 2) { w3(4); w3(4); w3(4); w3(4); }
|
||||
else { w0(4); P1; w0(4); P1; }
|
||||
{
|
||||
if (pi->mode >= 2) {
|
||||
w3(4); w3(4); w3(4); w3(4);
|
||||
} else {
|
||||
w0(4); P1; w0(4); P1;
|
||||
}
|
||||
CCP(0x30);
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
}
|
||||
|
||||
#define RESET_WAIT 200
|
||||
|
||||
static int on26_test_port(struct pi_adapter *pi) /* hard reset */
|
||||
/* hard reset */
|
||||
static int on26_test_port(struct pi_adapter *pi)
|
||||
{
|
||||
int i, m, d, x = 0, y = 0;
|
||||
|
||||
{ int i, m, d, x=0, y=0;
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
|
||||
pi->saved_r0 = r0();
|
||||
pi->saved_r2 = r2();
|
||||
d = pi->delay;
|
||||
m = pi->mode;
|
||||
pi->delay = 5;
|
||||
pi->mode = 0;
|
||||
|
||||
d = pi->delay;
|
||||
m = pi->mode;
|
||||
pi->delay = 5;
|
||||
pi->mode = 0;
|
||||
w2(0xc);
|
||||
|
||||
w2(0xc);
|
||||
CCP(0x30); CCP(0);
|
||||
|
||||
CCP(0x30); CCP(0);
|
||||
w0(0xfe); w0(0xaa); w0(0x55); w0(0); w0(0xff);
|
||||
i = ((r1() & 0xf0) << 4); w0(0x87);
|
||||
i |= (r1() & 0xf0); w0(0x78);
|
||||
w0(0x20); w2(4); w2(5);
|
||||
i |= ((r1() & 0xf0) >> 4);
|
||||
w2(4); w0(0xff);
|
||||
|
||||
w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);
|
||||
i = ((r1() & 0xf0) << 4); w0(0x87);
|
||||
i |= (r1() & 0xf0); w0(0x78);
|
||||
w0(0x20);w2(4);w2(5);
|
||||
i |= ((r1() & 0xf0) >> 4);
|
||||
w2(4);w0(0xff);
|
||||
if (i == 0xb5f) {
|
||||
w0(2); P1; w0(0); P2;
|
||||
w0(3); P1; w0(0); P2;
|
||||
w0(2); P1; w0(8); P2; udelay(100);
|
||||
w0(2); P1; w0(0xa); P2; udelay(100);
|
||||
w0(2); P1; w0(8); P2; udelay(1000);
|
||||
|
||||
if (i == 0xb5f) {
|
||||
on26_write_regr(pi, 0, 6, 0xa0);
|
||||
|
||||
w0(2); P1; w0(0); P2;
|
||||
w0(3); P1; w0(0); P2;
|
||||
w0(2); P1; w0(8); P2; udelay(100);
|
||||
w0(2); P1; w0(0xa); P2; udelay(100);
|
||||
w0(2); P1; w0(8); P2; udelay(1000);
|
||||
|
||||
on26_write_regr(pi,0,6,0xa0);
|
||||
for (i = 0; i < RESET_WAIT; i++) {
|
||||
on26_write_regr(pi, 0, 6, 0xa0);
|
||||
x = on26_read_regr(pi, 0, 7);
|
||||
on26_write_regr(pi, 0, 6, 0xb0);
|
||||
y = on26_read_regr(pi, 0, 7);
|
||||
if (!((x & 0x80) || (y & 0x80)))
|
||||
break;
|
||||
mdelay(100);
|
||||
}
|
||||
|
||||
for (i=0;i<RESET_WAIT;i++) {
|
||||
on26_write_regr(pi,0,6,0xa0);
|
||||
x = on26_read_regr(pi,0,7);
|
||||
on26_write_regr(pi,0,6,0xb0);
|
||||
y = on26_read_regr(pi,0,7);
|
||||
if (!((x&0x80)||(y&0x80))) break;
|
||||
mdelay(100);
|
||||
}
|
||||
if (i == RESET_WAIT)
|
||||
dev_err(&pi->dev,
|
||||
"on26: Device reset failed (%x,%x)\n", x, y);
|
||||
|
||||
if (i == RESET_WAIT)
|
||||
dev_err(&pi->dev, "on26: Device reset failed (%x,%x)\n", x, y);
|
||||
w0(4); P1; w0(4); P1;
|
||||
}
|
||||
|
||||
w0(4); P1; w0(4); P1;
|
||||
}
|
||||
CCP(0x30);
|
||||
|
||||
CCP(0x30);
|
||||
pi->delay = d;
|
||||
pi->mode = m;
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
|
||||
pi->delay = d;
|
||||
pi->mode = m;
|
||||
w0(pi->saved_r0);
|
||||
w2(pi->saved_r2);
|
||||
|
||||
return 5;
|
||||
return 5;
|
||||
}
|
||||
|
||||
|
||||
static void on26_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int k, a, b;
|
||||
|
||||
{ int k, a, b;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1;
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1;
|
||||
udelay(10);
|
||||
for (k=0;k<count;k++) {
|
||||
w2(6); a = r1();
|
||||
w2(4); b = r1();
|
||||
buf[k] = j44(a,b);
|
||||
}
|
||||
w0(2); P1; w0(8); P2;
|
||||
break;
|
||||
|
||||
case 1: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1;
|
||||
for (k = 0; k < count; k++) {
|
||||
w2(6); a = r1();
|
||||
w2(4); b = r1();
|
||||
buf[k] = j44(a, b);
|
||||
}
|
||||
w0(2); P1; w0(8); P2;
|
||||
break;
|
||||
case 1:
|
||||
w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1;
|
||||
udelay(10);
|
||||
for (k=0;k<count/2;k++) {
|
||||
w2(0x26); buf[2*k] = r0();
|
||||
w2(0x24); buf[2*k+1] = r0();
|
||||
}
|
||||
w0(2); P1; w0(9); P2;
|
||||
break;
|
||||
|
||||
case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w2(0x26); buf[2 * k] = r0();
|
||||
w2(0x24); buf[2 * k + 1] = r0();
|
||||
}
|
||||
w0(2); P1; w0(9); P2;
|
||||
break;
|
||||
case 2:
|
||||
w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||
w3(0); w3(0); w2(0x24);
|
||||
udelay(10);
|
||||
for (k=0;k<count;k++) buf[k] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||
w3(0); w3(0); w2(0x24);
|
||||
udelay(10);
|
||||
for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||
w3(0); w3(0); w2(0x24);
|
||||
udelay(10);
|
||||
for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
|
||||
w2(4);
|
||||
break;
|
||||
|
||||
}
|
||||
for (k = 0; k < count; k++)
|
||||
buf[k] = r4();
|
||||
w2(4);
|
||||
break;
|
||||
case 3:
|
||||
w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||
w3(0); w3(0); w2(0x24);
|
||||
udelay(10);
|
||||
for (k = 0; k < count / 2; k++)
|
||||
((u16 *)buf)[k] = r4w();
|
||||
w2(4);
|
||||
break;
|
||||
case 4:
|
||||
w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||
w3(0); w3(0); w2(0x24);
|
||||
udelay(10);
|
||||
for (k = 0; k < count / 4; k++)
|
||||
((u32 *)buf)[k] = r4l();
|
||||
w2(4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void on26_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||
{
|
||||
int k;
|
||||
|
||||
{ int k;
|
||||
|
||||
switch (pi->mode) {
|
||||
|
||||
case 0:
|
||||
case 1: w0(1); P1; w0(1); P2;
|
||||
w0(2); P1; w0(0x18+pi->mode); P2; w0(0); P1;
|
||||
switch (pi->mode) {
|
||||
case 0:
|
||||
case 1:
|
||||
w0(1); P1; w0(1); P2;
|
||||
w0(2); P1; w0(0x18 + pi->mode); P2; w0(0); P1;
|
||||
udelay(10);
|
||||
for (k=0;k<count/2;k++) {
|
||||
w2(5); w0(buf[2*k]);
|
||||
w2(7); w0(buf[2*k+1]);
|
||||
}
|
||||
w2(5); w2(4);
|
||||
w0(2); P1; w0(8+pi->mode); P2;
|
||||
break;
|
||||
|
||||
case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||
for (k = 0; k < count / 2; k++) {
|
||||
w2(5); w0(buf[2 * k]);
|
||||
w2(7); w0(buf[2 * k + 1]);
|
||||
}
|
||||
w2(5); w2(4);
|
||||
w0(2); P1; w0(8 + pi->mode); P2;
|
||||
break;
|
||||
case 2:
|
||||
w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||
w3(0); w3(0); w2(0xc5);
|
||||
udelay(10);
|
||||
for (k=0;k<count;k++) w4(buf[k]);
|
||||
for (k = 0; k < count; k++)
|
||||
w4(buf[k]);
|
||||
w2(0xc4);
|
||||
break;
|
||||
|
||||
case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||
w3(0); w3(0); w2(0xc5);
|
||||
udelay(10);
|
||||
for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
|
||||
w2(0xc4);
|
||||
break;
|
||||
|
||||
case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||
w3(0); w3(0); w2(0xc5);
|
||||
udelay(10);
|
||||
for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
|
||||
w2(0xc4);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case 3:
|
||||
w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||
w3(0); w3(0); w2(0xc5);
|
||||
udelay(10);
|
||||
for (k = 0; k < count / 2; k++)
|
||||
w4w(((u16 *)buf)[k]);
|
||||
w2(0xc4);
|
||||
break;
|
||||
case 4:
|
||||
w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||
w3(0); w3(0); w2(0xc5);
|
||||
udelay(10);
|
||||
for (k = 0; k < count / 4; k++)
|
||||
w4l(((u32 *)buf)[k]);
|
||||
w2(0xc4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void on26_log_adapter(struct pi_adapter *pi)
|
||||
{
|
||||
char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
|
||||
|
||||
{ char *mode_string[5] = {"4-bit","8-bit","EPP-8",
|
||||
"EPP-16","EPP-32"};
|
||||
|
||||
dev_info(&pi->dev, "OnSpec 90c26 at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
dev_info(&pi->dev,
|
||||
"OnSpec 90c26 at 0x%x, mode %d (%s), delay %d\n",
|
||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||
}
|
||||
|
||||
static struct pi_protocol on26 = {
|
||||
|
|
|
@ -223,7 +223,7 @@ static int pata_platform_probe(struct platform_device *pdev)
|
|||
|
||||
static struct platform_driver pata_platform_driver = {
|
||||
.probe = pata_platform_probe,
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.driver = {
|
||||
.name = DRV_NAME,
|
||||
},
|
||||
|
|
|
@ -614,7 +614,7 @@ static SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops,
|
|||
ahci_highbank_suspend, ahci_highbank_resume);
|
||||
|
||||
static struct platform_driver ahci_highbank_driver = {
|
||||
.remove = ata_platform_remove_one,
|
||||
.remove_new = ata_platform_remove_one,
|
||||
.driver = {
|
||||
.name = "highbank-ahci",
|
||||
.of_match_table = ahci_of_match,
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <scsi/scsi.h>
|
||||
#include <linux/libata.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#define DRV_NAME "sata_svw"
|
||||
#define DRV_VERSION "2.3"
|
||||
|
@ -319,10 +320,11 @@ static int k2_sata_show_info(struct seq_file *m, struct Scsi_Host *shost)
|
|||
/* Match it to a port node */
|
||||
index = (ap == ap->host->ports[0]) ? 0 : 1;
|
||||
for (np = np->child; np != NULL; np = np->sibling) {
|
||||
const u32 *reg = of_get_property(np, "reg", NULL);
|
||||
if (!reg)
|
||||
u64 reg;
|
||||
|
||||
if (of_property_read_reg(np, 0, ®, NULL))
|
||||
continue;
|
||||
if (index == *reg) {
|
||||
if (index == reg) {
|
||||
seq_printf(m, "devspec: %pOF\n", np);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -872,8 +872,7 @@ int sas_change_queue_depth(struct scsi_device *sdev, int depth)
|
|||
struct domain_device *dev = sdev_to_domain_dev(sdev);
|
||||
|
||||
if (dev_is_sata(dev))
|
||||
return ata_change_queue_depth(dev->sata_dev.ap,
|
||||
sas_to_ata_dev(dev), sdev, depth);
|
||||
return ata_change_queue_depth(dev->sata_dev.ap, sdev, depth);
|
||||
|
||||
if (!sdev->tagged_supported)
|
||||
depth = 1;
|
||||
|
|
|
@ -1144,8 +1144,8 @@ extern int ata_scsi_slave_config(struct scsi_device *sdev);
|
|||
extern void ata_scsi_slave_destroy(struct scsi_device *sdev);
|
||||
extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
|
||||
int queue_depth);
|
||||
extern int ata_change_queue_depth(struct ata_port *ap, struct ata_device *dev,
|
||||
struct scsi_device *sdev, int queue_depth);
|
||||
extern int ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
|
||||
int queue_depth);
|
||||
extern struct ata_device *ata_dev_pair(struct ata_device *adev);
|
||||
extern int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev);
|
||||
extern void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap);
|
||||
|
@ -1276,7 +1276,7 @@ extern int ata_pci_device_resume(struct pci_dev *pdev);
|
|||
|
||||
struct platform_device;
|
||||
|
||||
extern int ata_platform_remove_one(struct platform_device *pdev);
|
||||
extern void ata_platform_remove_one(struct platform_device *pdev);
|
||||
|
||||
/*
|
||||
* ACPI - drivers/ata/libata-acpi.c
|
||||
|
|
Загрузка…
Ссылка в новой задаче