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:
commit
1546cd4bfd
124
Documentation/devicetree/bindings/ata/rockchip,dwc-ahci.yaml
Normal file
124
Documentation/devicetree/bindings/ata/rockchip,dwc-ahci.yaml
Normal file
@ -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)
|
PM-alive clock, RxOOB detection clock, embedded PHYs reference (Rx/Tx)
|
||||||
clock, etc.
|
clock, etc.
|
||||||
minItems: 1
|
minItems: 1
|
||||||
maxItems: 4
|
maxItems: 6
|
||||||
|
|
||||||
clock-names:
|
clock-names:
|
||||||
minItems: 1
|
minItems: 1
|
||||||
maxItems: 4
|
maxItems: 6
|
||||||
items:
|
items:
|
||||||
oneOf:
|
oneOf:
|
||||||
- description: Application APB/AHB/AXI BIU clock
|
- description: Application APB/AHB/AXI BIU clock
|
||||||
@ -48,6 +48,10 @@ properties:
|
|||||||
const: pmalive
|
const: pmalive
|
||||||
- description: RxOOB detection clock
|
- description: RxOOB detection clock
|
||||||
const: rxoob
|
const: rxoob
|
||||||
|
- description: PHY Transmit Clock
|
||||||
|
const: asic
|
||||||
|
- description: PHY Receive Clock
|
||||||
|
const: rbc
|
||||||
- description: SATA Ports reference clock
|
- description: SATA Ports reference clock
|
||||||
const: ref
|
const: ref
|
||||||
|
|
||||||
|
@ -13,6 +13,15 @@ description:
|
|||||||
This document defines device tree bindings for the generic Synopsys DWC
|
This document defines device tree bindings for the generic Synopsys DWC
|
||||||
implementation of the AHCI SATA controller.
|
implementation of the AHCI SATA controller.
|
||||||
|
|
||||||
|
select:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- snps,dwc-ahci
|
||||||
|
- snps,spear-ahci
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: snps,dwc-ahci-common.yaml#
|
- $ref: snps,dwc-ahci-common.yaml#
|
||||||
|
|
||||||
@ -23,10 +32,6 @@ properties:
|
|||||||
const: snps,dwc-ahci
|
const: snps,dwc-ahci
|
||||||
- description: SPEAr1340 AHCI SATA device
|
- description: SPEAr1340 AHCI SATA device
|
||||||
const: snps,spear-ahci
|
const: snps,spear-ahci
|
||||||
- description: Rockhip RK3568 AHCI controller
|
|
||||||
items:
|
|
||||||
- const: rockchip,rk3568-dwc-ahci
|
|
||||||
- const: snps,dwc-ahci
|
|
||||||
|
|
||||||
patternProperties:
|
patternProperties:
|
||||||
"^sata-port@[0-9a-e]$":
|
"^sata-port@[0-9a-e]$":
|
||||||
|
@ -31,8 +31,14 @@ properties:
|
|||||||
- const: pipe
|
- const: pipe
|
||||||
|
|
||||||
resets:
|
resets:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 2
|
||||||
|
|
||||||
|
reset-names:
|
||||||
|
minItems: 1
|
||||||
items:
|
items:
|
||||||
- description: exclusive PHY reset line
|
- const: phy
|
||||||
|
- const: apb
|
||||||
|
|
||||||
rockchip,enable-ssc:
|
rockchip,enable-ssc:
|
||||||
type: boolean
|
type: boolean
|
||||||
@ -78,6 +84,32 @@ required:
|
|||||||
- rockchip,pipe-phy-grf
|
- rockchip,pipe-phy-grf
|
||||||
- "#phy-cells"
|
- "#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
|
additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
|
@ -544,7 +544,7 @@ out_reset:
|
|||||||
return ret;
|
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 ata_host *host = dev_get_drvdata(&pdev->dev);
|
||||||
struct ahci_host_priv *hpriv = host->private_data;
|
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);
|
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)
|
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 = {
|
static struct platform_driver brcm_ahci_driver = {
|
||||||
.probe = brcm_ahci_probe,
|
.probe = brcm_ahci_probe,
|
||||||
.remove = brcm_ahci_remove,
|
.remove_new = brcm_ahci_remove,
|
||||||
.shutdown = brcm_ahci_shutdown,
|
.shutdown = brcm_ahci_shutdown,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
|
@ -369,7 +369,7 @@ MODULE_DEVICE_TABLE(of, ceva_ahci_of_match);
|
|||||||
|
|
||||||
static struct platform_driver ceva_ahci_driver = {
|
static struct platform_driver ceva_ahci_driver = {
|
||||||
.probe = ceva_ahci_probe,
|
.probe = ceva_ahci_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
.of_match_table = ceva_ahci_of_match,
|
.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 = {
|
static struct platform_driver ahci_da850_driver = {
|
||||||
.probe = ahci_da850_probe,
|
.probe = ahci_da850_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
.of_match_table = ahci_da850_of_match,
|
.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 = {
|
static struct platform_driver ahci_dm816_driver = {
|
||||||
.probe = ahci_dm816_probe,
|
.probe = ahci_dm816_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = AHCI_DM816_DRV_NAME,
|
.name = AHCI_DM816_DRV_NAME,
|
||||||
.of_match_table = ahci_dm816_of_match,
|
.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 = {
|
static struct platform_driver ahci_dwc_driver = {
|
||||||
.probe = ahci_dwc_probe,
|
.probe = ahci_dwc_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.shutdown = ahci_platform_shutdown,
|
.shutdown = ahci_platform_shutdown,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.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 = {
|
static struct platform_driver imx_ahci_driver = {
|
||||||
.probe = imx_ahci_probe,
|
.probe = imx_ahci_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
.of_match_table = imx_ahci_of_match,
|
.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 = {
|
static struct platform_driver mtk_ahci_driver = {
|
||||||
.probe = mtk_ahci_probe,
|
.probe = mtk_ahci_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
.of_match_table = ahci_of_match,
|
.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 = {
|
static struct platform_driver ahci_mvebu_driver = {
|
||||||
.probe = ahci_mvebu_probe,
|
.probe = ahci_mvebu_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.suspend = ahci_mvebu_suspend,
|
.suspend = ahci_mvebu_suspend,
|
||||||
.resume = ahci_mvebu_resume,
|
.resume = ahci_mvebu_resume,
|
||||||
.driver = {
|
.driver = {
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
|
|
||||||
#include <asm/octeon/octeon.h>
|
#include <asm/octeon/octeon.h>
|
||||||
#include <asm/bitfield.h>
|
|
||||||
|
|
||||||
#define CVMX_SATA_UCTL_SHIM_CFG 0xE8
|
#define CVMX_SATA_UCTL_SHIM_CFG 0xE8
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ MODULE_DEVICE_TABLE(acpi, ahci_acpi_match);
|
|||||||
|
|
||||||
static struct platform_driver ahci_driver = {
|
static struct platform_driver ahci_driver = {
|
||||||
.probe = ahci_probe,
|
.probe = ahci_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.shutdown = ahci_platform_shutdown,
|
.shutdown = ahci_platform_shutdown,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.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 = {
|
static struct platform_driver ahci_qoriq_driver = {
|
||||||
.probe = ahci_qoriq_probe,
|
.probe = ahci_qoriq_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
.of_match_table = ahci_qoriq_of_match,
|
.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 = {
|
static struct platform_driver ahci_seattle_driver = {
|
||||||
.probe = ahci_seattle_probe,
|
.probe = ahci_seattle_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
.acpi_match_table = ahci_acpi_match,
|
.acpi_match_table = ahci_acpi_match,
|
||||||
|
@ -239,7 +239,7 @@ static struct platform_driver st_ahci_driver = {
|
|||||||
.of_match_table = st_ahci_match,
|
.of_match_table = st_ahci_match,
|
||||||
},
|
},
|
||||||
.probe = st_ahci_probe,
|
.probe = st_ahci_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
};
|
};
|
||||||
module_platform_driver(st_ahci_driver);
|
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 = {
|
static struct platform_driver ahci_sunxi_driver = {
|
||||||
.probe = ahci_sunxi_probe,
|
.probe = ahci_sunxi_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
.of_match_table = ahci_sunxi_of_match,
|
.of_match_table = ahci_sunxi_of_match,
|
||||||
|
@ -609,7 +609,7 @@ deinit_controller:
|
|||||||
|
|
||||||
static struct platform_driver tegra_ahci_driver = {
|
static struct platform_driver tegra_ahci_driver = {
|
||||||
.probe = tegra_ahci_probe,
|
.probe = tegra_ahci_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
.of_match_table = tegra_ahci_of_match,
|
.of_match_table = tegra_ahci_of_match,
|
||||||
|
@ -868,7 +868,7 @@ disable_resources:
|
|||||||
|
|
||||||
static struct platform_driver xgene_ahci_driver = {
|
static struct platform_driver xgene_ahci_driver = {
|
||||||
.probe = xgene_ahci_probe,
|
.probe = xgene_ahci_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
.of_match_table = xgene_ahci_of_match,
|
.of_match_table = xgene_ahci_of_match,
|
||||||
|
@ -975,44 +975,43 @@ int ahci_reset_controller(struct ata_host *host)
|
|||||||
void __iomem *mmio = hpriv->mmio;
|
void __iomem *mmio = hpriv->mmio;
|
||||||
u32 tmp;
|
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);
|
ahci_enable_ahci(mmio);
|
||||||
|
|
||||||
/* global controller reset */
|
/* Global controller reset */
|
||||||
if (!ahci_skip_host_reset) {
|
if (ahci_skip_host_reset) {
|
||||||
tmp = readl(mmio + HOST_CTL);
|
dev_info(host->dev, "Skipping global host reset\n");
|
||||||
if ((tmp & HOST_RESET) == 0) {
|
return 0;
|
||||||
writel(tmp | HOST_RESET, mmio + HOST_CTL);
|
}
|
||||||
readl(mmio + HOST_CTL); /* flush */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
tmp = readl(mmio + HOST_CTL);
|
||||||
* to perform host reset, OS should set HOST_RESET
|
if (!(tmp & HOST_RESET)) {
|
||||||
* and poll until this bit is read to be "0".
|
writel(tmp | HOST_RESET, mmio + HOST_CTL);
|
||||||
* reset must complete within 1 second, or
|
readl(mmio + HOST_CTL); /* flush */
|
||||||
* 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",
|
* To perform host reset, OS should set HOST_RESET and poll until this
|
||||||
tmp);
|
* bit is read to be "0". Reset must complete within 1 second, or the
|
||||||
return -EIO;
|
* 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 */
|
/* Turn on AHCI mode */
|
||||||
ahci_enable_ahci(mmio);
|
ahci_enable_ahci(mmio);
|
||||||
|
|
||||||
/* Some registers might be cleared on reset. Restore
|
/* Some registers might be cleared on reset. Restore initial values. */
|
||||||
* initial values.
|
if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO))
|
||||||
*/
|
ahci_restore_initial_config(host);
|
||||||
if (!(hpriv->flags & AHCI_HFLAG_NO_WRITE_TO_RO))
|
|
||||||
ahci_restore_initial_config(host);
|
|
||||||
} else
|
|
||||||
dev_info(host->dev, "skipping global host reset\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -3802,11 +3802,7 @@ int ata_dev_revalidate(struct ata_device *dev, unsigned int new_class,
|
|||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* fail early if !ATA && !ATAPI to avoid issuing [P]IDENTIFY to PMP */
|
/* fail early if !ATA && !ATAPI to avoid issuing [P]IDENTIFY to PMP */
|
||||||
if (ata_class_enabled(new_class) &&
|
if (ata_class_enabled(new_class) && new_class == ATA_DEV_PMP) {
|
||||||
new_class != ATA_DEV_ATA &&
|
|
||||||
new_class != ATA_DEV_ATAPI &&
|
|
||||||
new_class != ATA_DEV_ZAC &&
|
|
||||||
new_class != ATA_DEV_SEMB) {
|
|
||||||
ata_dev_info(dev, "class mismatch %u != %u\n",
|
ata_dev_info(dev, "class mismatch %u != %u\n",
|
||||||
dev->class, new_class);
|
dev->class, new_class);
|
||||||
rc = -ENODEV;
|
rc = -ENODEV;
|
||||||
@ -6142,13 +6138,11 @@ EXPORT_SYMBOL_GPL(ata_pci_device_resume);
|
|||||||
* LOCKING:
|
* LOCKING:
|
||||||
* Inherited from platform layer (may sleep).
|
* 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);
|
struct ata_host *host = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
ata_host_detach(host);
|
ata_host_detach(host);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(ata_platform_remove_one);
|
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);
|
verdict = ata_eh_speed_down_verdict(dev);
|
||||||
|
|
||||||
/* turn off NCQ? */
|
/* turn off NCQ? */
|
||||||
if ((verdict & ATA_EH_SPDN_NCQ_OFF) &&
|
if ((verdict & ATA_EH_SPDN_NCQ_OFF) && ata_ncq_enabled(dev)) {
|
||||||
(dev->flags & (ATA_DFLAG_PIO | ATA_DFLAG_NCQ |
|
|
||||||
ATA_DFLAG_NCQ_OFF)) == ATA_DFLAG_NCQ) {
|
|
||||||
dev->flags |= ATA_DFLAG_NCQ_OFF;
|
dev->flags |= ATA_DFLAG_NCQ_OFF;
|
||||||
ata_dev_warn(dev, "NCQ disabled due to excessive errors\n");
|
ata_dev_warn(dev, "NCQ disabled due to excessive errors\n");
|
||||||
goto done;
|
goto done;
|
||||||
@ -3813,16 +3811,29 @@ void ata_eh_finish(struct ata_port *ap)
|
|||||||
* generate sense data in this function,
|
* generate sense data in this function,
|
||||||
* considering both err_mask and tf.
|
* 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);
|
ata_eh_qc_retry(qc);
|
||||||
else
|
} else {
|
||||||
ata_eh_qc_complete(qc);
|
ata_eh_qc_complete(qc);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
|
if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
|
||||||
ata_eh_qc_complete(qc);
|
ata_eh_qc_complete(qc);
|
||||||
} else {
|
} else {
|
||||||
/* feed zero TF to sense generation */
|
/* feed zero TF to sense generation */
|
||||||
memset(&qc->result_tf, 0, sizeof(qc->result_tf));
|
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);
|
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
|
* ata_change_queue_depth - Set a device maximum queue depth
|
||||||
* @ap: ATA port of the target device
|
* @ap: ATA port of the target device
|
||||||
* @dev: target ATA device
|
|
||||||
* @sdev: SCSI device to configure queue depth for
|
* @sdev: SCSI device to configure queue depth for
|
||||||
* @queue_depth: new queue depth
|
* @queue_depth: new queue depth
|
||||||
*
|
*
|
||||||
@ -1031,33 +1030,47 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
|
|||||||
* and libata.
|
* and libata.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int ata_change_queue_depth(struct ata_port *ap, struct ata_device *dev,
|
int ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
|
||||||
struct scsi_device *sdev, int queue_depth)
|
int queue_depth)
|
||||||
{
|
{
|
||||||
|
struct ata_device *dev;
|
||||||
unsigned long flags;
|
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);
|
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;
|
dev->flags |= ATA_DFLAG_NCQ_OFF;
|
||||||
queue_depth = 1;
|
queue_depth = 1;
|
||||||
|
} else {
|
||||||
|
dev->flags &= ~ATA_DFLAG_NCQ_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(ap->lock, flags);
|
spin_unlock_irqrestore(ap->lock, flags);
|
||||||
|
|
||||||
/* limit and apply queue depth */
|
if (queue_depth == sdev->queue_depth)
|
||||||
queue_depth = min(queue_depth, sdev->host->can_queue);
|
return sdev->queue_depth;
|
||||||
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;
|
|
||||||
|
|
||||||
return scsi_change_queue_depth(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);
|
struct ata_port *ap = ata_shost_to_port(sdev->host);
|
||||||
|
|
||||||
return ata_change_queue_depth(ap, ata_scsi_find_dev(ap, sdev),
|
return ata_change_queue_depth(ap, sdev, queue_depth);
|
||||||
sdev, queue_depth);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(ata_scsi_change_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)
|
if (dev->flags & ATA_DFLAG_AN)
|
||||||
set_bit(SDEV_EVT_MEDIA_CHANGE, sdev->supported_events);
|
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(sdev->host->can_queue, ata_id_queue_depth(dev->id));
|
||||||
depth = min(ATA_MAX_QUEUE, depth);
|
depth = min(ATA_MAX_QUEUE, depth);
|
||||||
scsi_change_queue_depth(sdev, 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,
|
.of_match_table = ixp4xx_pata_of_match,
|
||||||
},
|
},
|
||||||
.probe = ixp4xx_pata_probe,
|
.probe = ixp4xx_pata_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_platform_driver(ixp4xx_pata_platform_driver);
|
module_platform_driver(ixp4xx_pata_platform_driver);
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/irq.h>
|
#include <linux/irq.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <scsi/scsi_host.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;
|
struct resource *res_cs0, *res_cs1;
|
||||||
|
|
||||||
bool is_16bit;
|
bool is_16bit;
|
||||||
const __be32 *cs_num;
|
u64 reg;
|
||||||
struct property *reg_prop;
|
|
||||||
int n_addr, n_size, reg_len;
|
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
void __iomem *cs0;
|
void __iomem *cs0;
|
||||||
void __iomem *cs1 = NULL;
|
void __iomem *cs1 = NULL;
|
||||||
@ -834,15 +833,10 @@ static int octeon_cf_probe(struct platform_device *pdev)
|
|||||||
else
|
else
|
||||||
is_16bit = false;
|
is_16bit = false;
|
||||||
|
|
||||||
n_addr = of_n_addr_cells(node);
|
rv = of_property_read_reg(node, 0, ®, NULL);
|
||||||
n_size = of_n_size_cells(node);
|
if (rv < 0)
|
||||||
|
return rv;
|
||||||
reg_prop = of_find_property(node, "reg", ®_len);
|
cf_port->cs0 = upper_32_bits(reg);
|
||||||
if (!reg_prop || reg_len < sizeof(__be32))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
cs_num = reg_prop->value;
|
|
||||||
cf_port->cs0 = be32_to_cpup(cs_num);
|
|
||||||
|
|
||||||
if (cf_port->is_true_ide) {
|
if (cf_port->is_true_ide) {
|
||||||
struct device_node *dma_node;
|
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,
|
cs1 = devm_ioremap(&pdev->dev, res_cs1->start,
|
||||||
resource_size(res_cs1));
|
resource_size(res_cs1));
|
||||||
if (!cs1)
|
if (!cs1)
|
||||||
return rv;
|
|
||||||
|
|
||||||
if (reg_len < (n_addr + n_size + 1) * sizeof(__be32))
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
cs_num += n_addr + n_size;
|
rv = of_property_read_reg(node, 1, ®, NULL);
|
||||||
cf_port->cs1 = be32_to_cpup(cs_num);
|
if (rv < 0)
|
||||||
|
return rv;
|
||||||
|
cf_port->cs1 = upper_32_bits(reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
res_cs0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
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,
|
.of_match_table = pata_of_platform_match,
|
||||||
},
|
},
|
||||||
.probe = pata_of_platform_probe,
|
.probe = pata_of_platform_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
};
|
};
|
||||||
|
|
||||||
module_platform_driver(pata_of_platform_driver);
|
module_platform_driver(pata_of_platform_driver);
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
aten.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
/*
|
||||||
Under the terms of the GNU General Public License.
|
* (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
||||||
|
*
|
||||||
aten.c is a low-level protocol driver for the ATEN EH-100
|
* 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
|
* parallel port adapter. The EH-100 supports 4-bit and 8-bit
|
||||||
modes only. There is also an EH-132 which supports EPP mode
|
* modes only. There is also an EH-132 which supports EPP mode
|
||||||
transfers. The EH-132 is not yet supported.
|
* transfers. The EH-132 is not yet supported.
|
||||||
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -20,36 +19,36 @@
|
|||||||
|
|
||||||
#define j44(a,b) ((((a>>4)&0x0f)|(b&0xf0))^0x88)
|
#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 int cont_map[2] = { 0x08, 0x20 };
|
||||||
|
|
||||||
static void aten_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
static void aten_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||||
|
{
|
||||||
{ int r;
|
int r = regr + cont_map[cont] + 0x80;
|
||||||
|
|
||||||
r = regr + cont_map[cont] + 0x80;
|
|
||||||
|
|
||||||
w0(r); w2(0xe); w2(6); w0(val); w2(7); w2(6); w2(0xc);
|
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)
|
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) {
|
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);
|
w2(7); w2(6); w2(0);
|
||||||
a = r1(); w0(0x10); b = r1(); w2(0xc);
|
a = r1(); w0(0x10); b = r1(); w2(0xc);
|
||||||
return j44(a,b);
|
return j44(a,b);
|
||||||
|
|
||||||
case 1: r |= 0x10;
|
case 1:
|
||||||
w0(r); w2(0xe); w2(6); w0(0xff);
|
r |= 0x10;
|
||||||
|
w0(r); w2(0xe); w2(6); w0(0xff);
|
||||||
w2(0x27); w2(0x26); w2(0x20);
|
w2(0x27); w2(0x26); w2(0x20);
|
||||||
a = r0();
|
a = r0();
|
||||||
w2(0x26); w2(0xc);
|
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)
|
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) {
|
switch (pi->mode) {
|
||||||
|
|
||||||
case 0: w0(0x48); w2(0xe); w2(6);
|
case 0:
|
||||||
for (k=0;k<count/2;k++) {
|
w0(0x48); w2(0xe); w2(6);
|
||||||
|
for (k = 0; k < count / 2; k++) {
|
||||||
w2(7); w2(6); w2(2);
|
w2(7); w2(6); w2(2);
|
||||||
a = r1(); w0(0x58); b = r1();
|
a = r1(); w0(0x58); b = r1();
|
||||||
w2(0); d = r1(); w0(0x48); c = r1();
|
w2(0); d = r1(); w0(0x48); c = r1();
|
||||||
buf[2*k] = j44(c,d);
|
buf[2 * k] = j44(c, d);
|
||||||
buf[2*k+1] = j44(a,b);
|
buf[2 * k + 1] = j44(a, b);
|
||||||
}
|
}
|
||||||
w2(0xc);
|
w2(0xc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: w0(0x58); w2(0xe); w2(6);
|
case 1:
|
||||||
for (k=0;k<count/2;k++) {
|
w0(0x58); w2(0xe); w2(6);
|
||||||
|
for (k = 0; k < count / 2; k++) {
|
||||||
w2(0x27); w2(0x26); w2(0x22);
|
w2(0x27); w2(0x26); w2(0x22);
|
||||||
a = r0(); w2(0x20); b = r0();
|
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);
|
w2(0x26); w2(0xc);
|
||||||
break;
|
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)
|
static void aten_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||||
|
{
|
||||||
{ int k;
|
int k;
|
||||||
|
|
||||||
w0(0x88); w2(0xe); w2(6);
|
w0(0x88); w2(0xe); w2(6);
|
||||||
for (k=0;k<count/2;k++) {
|
for (k = 0; k < count / 2; k++) {
|
||||||
w0(buf[2*k+1]); w2(0xe); w2(6);
|
w0(buf[2 * k + 1]); w2(0xe); w2(6);
|
||||||
w0(buf[2*k]); w2(7); w2(6);
|
w0(buf[2 * k]); w2(7); w2(6);
|
||||||
}
|
}
|
||||||
w2(0xc);
|
w2(0xc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void aten_connect(struct pi_adapter *pi)
|
static void aten_connect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ pi->saved_r0 = r0();
|
pi->saved_r0 = r0();
|
||||||
pi->saved_r2 = r2();
|
pi->saved_r2 = r2();
|
||||||
w2(0xc);
|
w2(0xc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void aten_disconnect(struct pi_adapter *pi)
|
static void aten_disconnect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ w0(pi->saved_r0);
|
w0(pi->saved_r0);
|
||||||
w2(pi->saved_r2);
|
w2(pi->saved_r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void aten_log_adapter(struct pi_adapter *pi)
|
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",
|
||||||
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);
|
||||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pi_protocol aten = {
|
static struct pi_protocol aten = {
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
bpck.c (c) 1996-8 Grant R. Guenther <grant@torque.net>
|
/*
|
||||||
Under the terms of the GNU General Public License.
|
* (c) 1996-1998 Grant R. Guenther <grant@torque.net>
|
||||||
|
*
|
||||||
bpck.c is a low-level protocol driver for the MicroSolutions
|
* bpck.c is a low-level protocol driver for the MicroSolutions
|
||||||
"backpack" parallel port IDE adapter.
|
* "backpack" parallel port IDE adapter.
|
||||||
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -29,59 +28,57 @@
|
|||||||
|
|
||||||
#define j44(l,h) (((l>>3)&0x7)|((l>>4)&0x8)|((h<<1)&0x70)|(h&0x80))
|
#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 = 0 - access the IDE register file
|
||||||
cont = 2 - use internal bpck register addressing
|
* cont = 1 - access the IDE command set
|
||||||
*/
|
* cont = 2 - use internal bpck register addressing
|
||||||
|
*/
|
||||||
static int cont_map[3] = { 0x40, 0x48, 0 };
|
static int cont_map[3] = { 0x40, 0x48, 0 };
|
||||||
|
|
||||||
static int bpck_read_regr(struct pi_adapter *pi, int cont, int regr)
|
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];
|
r = regr + cont_map[cont];
|
||||||
|
|
||||||
switch (pi->mode) {
|
switch (pi->mode) {
|
||||||
|
case 0:
|
||||||
case 0: w0(r & 0xf); w0(r); t2(2); t2(4);
|
w0(r & 0xf); w0(r); t2(2); t2(4);
|
||||||
l = r1();
|
l = r1();
|
||||||
t2(4);
|
t2(4);
|
||||||
h = r1();
|
h = r1();
|
||||||
return j44(l,h);
|
return j44(l, h);
|
||||||
|
case 1:
|
||||||
case 1: w0(r & 0xf); w0(r); t2(2);
|
w0(r & 0xf); w0(r); t2(2);
|
||||||
e2(); t2(0x20);
|
e2(); t2(0x20);
|
||||||
t2(4); h = r0();
|
t2(4); h = r0();
|
||||||
t2(1); t2(0x20);
|
t2(1); t2(0x20);
|
||||||
return h;
|
return h;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
case 4: w0(r); w2(9); w2(0); w2(0x20);
|
case 4:
|
||||||
|
w0(r); w2(9); w2(0); w2(0x20);
|
||||||
h = r4();
|
h = r4();
|
||||||
w2(0);
|
w2(0);
|
||||||
return h;
|
return h;
|
||||||
|
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bpck_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
static void bpck_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||||
|
{
|
||||||
{ int r;
|
int r;
|
||||||
|
|
||||||
r = regr + cont_map[cont];
|
r = regr + cont_map[cont];
|
||||||
|
|
||||||
switch (pi->mode) {
|
switch (pi->mode) {
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
case 1: w0(r);
|
case 1: w0(r);
|
||||||
t2(2);
|
t2(2);
|
||||||
w0(val);
|
w0(val);
|
||||||
o2(); t2(4); t2(1);
|
o2(); t2(4); t2(1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
case 4: w0(r); w2(9); w2(0);
|
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))
|
#define RR(r) (bpck_read_regr(pi,2,r))
|
||||||
|
|
||||||
static void bpck_write_block(struct pi_adapter *pi, char *buf, int count)
|
static void bpck_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||||
|
{
|
||||||
{ int i;
|
int i;
|
||||||
|
|
||||||
switch (pi->mode) {
|
switch (pi->mode) {
|
||||||
|
|
||||||
case 0: WR(4,0x40);
|
case 0:
|
||||||
|
WR(4, 0x40);
|
||||||
w0(0x40); t2(2); t2(1);
|
w0(0x40); t2(2); t2(1);
|
||||||
for (i=0;i<count;i++) { w0(buf[i]); t2(4); }
|
for (i = 0; i < count; i++) {
|
||||||
WR(4,0);
|
w0(buf[i]);
|
||||||
|
t2(4);
|
||||||
|
}
|
||||||
|
WR(4, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: WR(4,0x50);
|
case 1:
|
||||||
w0(0x40); t2(2); t2(1);
|
WR(4, 0x50);
|
||||||
for (i=0;i<count;i++) { w0(buf[i]); t2(4); }
|
w0(0x40); t2(2); t2(1);
|
||||||
WR(4,0x10);
|
for (i = 0; i < count; i++) {
|
||||||
|
w0(buf[i]);
|
||||||
|
t2(4);
|
||||||
|
}
|
||||||
|
WR(4, 0x10);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: WR(4,0x48);
|
case 2:
|
||||||
|
WR(4, 0x48);
|
||||||
w0(0x40); w2(9); w2(0); w2(1);
|
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);
|
w2(0);
|
||||||
WR(4,8);
|
WR(4, 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: WR(4,0x48);
|
case 3:
|
||||||
w0(0x40); w2(9); w2(0); w2(1);
|
WR(4, 0x48);
|
||||||
for (i=0;i<count/2;i++) w4w(((u16 *)buf)[i]);
|
w0(0x40); w2(9); w2(0); w2(1);
|
||||||
w2(0);
|
for (i = 0; i < count / 2; i++)
|
||||||
WR(4,8);
|
w4w(((u16 *)buf)[i]);
|
||||||
break;
|
w2(0);
|
||||||
|
WR(4, 8);
|
||||||
case 4: WR(4,0x48);
|
break;
|
||||||
w0(0x40); w2(9); w2(0); w2(1);
|
|
||||||
for (i=0;i<count/4;i++) w4l(((u32 *)buf)[i]);
|
case 4:
|
||||||
w2(0);
|
WR(4, 0x48);
|
||||||
WR(4,8);
|
w0(0x40); w2(9); w2(0); w2(1);
|
||||||
break;
|
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)
|
static void bpck_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||||
|
{
|
||||||
{ int i, l, h;
|
int i, l, h;
|
||||||
|
|
||||||
switch (pi->mode) {
|
switch (pi->mode) {
|
||||||
|
|
||||||
case 0: WR(4,0x40);
|
case 0:
|
||||||
|
WR(4, 0x40);
|
||||||
w0(0x40); t2(2);
|
w0(0x40); t2(2);
|
||||||
for (i=0;i<count;i++) {
|
for (i = 0; i < count; i++) {
|
||||||
t2(4); l = r1();
|
t2(4); l = r1();
|
||||||
t2(4); h = r1();
|
t2(4); h = r1();
|
||||||
buf[i] = j44(l,h);
|
buf[i] = j44(l, h);
|
||||||
}
|
}
|
||||||
WR(4,0);
|
WR(4, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: WR(4,0x50);
|
case 1:
|
||||||
|
WR(4, 0x50);
|
||||||
w0(0x40); t2(2); t2(0x20);
|
w0(0x40); t2(2); t2(0x20);
|
||||||
for(i=0;i<count;i++) { t2(4); buf[i] = r0(); }
|
for (i = 0; i < count; i++) {
|
||||||
t2(1); t2(0x20);
|
t2(4);
|
||||||
WR(4,0x10);
|
buf[i] = r0();
|
||||||
|
}
|
||||||
|
t2(1); t2(0x20);
|
||||||
|
WR(4, 0x10);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: WR(4,0x48);
|
case 2:
|
||||||
|
WR(4, 0x48);
|
||||||
w0(0x40); w2(9); w2(0); w2(0x20);
|
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);
|
w2(0);
|
||||||
WR(4,8);
|
WR(4, 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: WR(4,0x48);
|
case 3:
|
||||||
w0(0x40); w2(9); w2(0); w2(0x20);
|
WR(4, 0x48);
|
||||||
for (i=0;i<count/2;i++) ((u16 *)buf)[i] = r4w();
|
w0(0x40); w2(9); w2(0); w2(0x20);
|
||||||
w2(0);
|
for (i = 0; i < count / 2; i++)
|
||||||
WR(4,8);
|
((u16 *)buf)[i] = r4w();
|
||||||
break;
|
w2(0);
|
||||||
|
WR(4, 8);
|
||||||
|
break;
|
||||||
|
|
||||||
case 4: WR(4,0x48);
|
case 4:
|
||||||
w0(0x40); w2(9); w2(0); w2(0x20);
|
WR(4, 0x48);
|
||||||
for (i=0;i<count/4;i++) ((u32 *)buf)[i] = r4l();
|
w0(0x40); w2(9); w2(0); w2(0x20);
|
||||||
w2(0);
|
for (i = 0; i < count / 4; i++)
|
||||||
WR(4,8);
|
((u32 *)buf)[i] = r4l();
|
||||||
break;
|
w2(0);
|
||||||
|
WR(4, 8);
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bpck_probe_unit(struct pi_adapter *pi)
|
static int bpck_probe_unit(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ int o1, o0, f7, id;
|
int o1, o0, f7, id;
|
||||||
int t, s;
|
int t, s;
|
||||||
|
|
||||||
id = pi->unit;
|
id = pi->unit;
|
||||||
s = 0;
|
s = 0;
|
||||||
w2(4); w2(0xe); r2(); t2(2);
|
w2(4); w2(0xe); r2(); t2(2);
|
||||||
o1 = r1()&0xf8;
|
o1 = r1()&0xf8;
|
||||||
o0 = r0();
|
o0 = r0();
|
||||||
w0(255-id); w2(4); w0(id);
|
w0(255-id); w2(4); w0(id);
|
||||||
t2(8); t2(8); t2(8);
|
t2(8); t2(8); t2(8);
|
||||||
t2(2); t = r1()&0xf8;
|
t2(2); t = r1()&0xf8;
|
||||||
f7 = ((id % 8) == 7);
|
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))) {
|
if ((t == o1) && ((!f7) || (s == o1))) {
|
||||||
w2(0x4c); w0(o0);
|
w2(0x4c); w0(o0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
t2(8); w0(0); t2(2); w2(0x4c); w0(o0);
|
t2(8); w0(0); t2(2); w2(0x4c); w0(o0);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bpck_connect(struct pi_adapter *pi)
|
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);
|
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);
|
t2(2); t2(2);
|
||||||
|
|
||||||
switch (pi->mode) {
|
switch (pi->mode) {
|
||||||
|
case 0:
|
||||||
case 0: t2(8); WR(4,0);
|
t2(8); WR(4, 0);
|
||||||
break;
|
break;
|
||||||
|
case 1:
|
||||||
case 1: t2(8); WR(4,0x10);
|
t2(8); WR(4, 0x10);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
case 4: w2(0); WR(4,8);
|
case 4:
|
||||||
|
w2(0); WR(4, 8);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WR(5,8);
|
WR(5,8);
|
||||||
|
|
||||||
/* if (pi->devtype == PI_PCD) { possibly wrong, purpose unknown */
|
/*
|
||||||
WR(0x46,0x10); /* fiddle with ESS logic ??? */
|
* Possibly wrong, purpose unknown (fiddle with ESS logic ???)
|
||||||
WR(0x4c,0x38);
|
* if (pi->devtype == PI_PCD) {
|
||||||
WR(0x4d,0x88);
|
*/
|
||||||
WR(0x46,0xa0);
|
WR(0x46, 0x10);
|
||||||
WR(0x41,0);
|
WR(0x4c, 0x38);
|
||||||
WR(0x4e,8);
|
WR(0x4d, 0x88);
|
||||||
/* }*/
|
WR(0x46, 0xa0);
|
||||||
|
WR(0x41, 0);
|
||||||
|
WR(0x4e, 8);
|
||||||
|
/* } */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bpck_disconnect(struct pi_adapter *pi)
|
static void bpck_disconnect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ w0(0);
|
w0(0);
|
||||||
if (pi->mode >= 2) { w2(9); w2(0); } else t2(2);
|
if (pi->mode >= 2) {
|
||||||
|
w2(9); w2(0);
|
||||||
|
} else {
|
||||||
|
t2(2);
|
||||||
|
}
|
||||||
w2(0x4c); w0(pi->saved_r0);
|
w2(0x4c); w0(pi->saved_r0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bpck_force_spp(struct pi_adapter *pi)
|
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 ... */
|
w2(0);
|
||||||
|
w0(4); w2(9); w2(0);
|
||||||
{ pi->saved_r0 = r0();
|
w0(0); w2(1); w2(3); w2(0);
|
||||||
w0(0xff-pi->unit); w2(4); w0(pi->unit);
|
w0(0); w2(9); w2(0);
|
||||||
t2(8); t2(8); t2(8);
|
w2(0x4c); w0(pi->saved_r0);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TEST_LEN 16
|
#define TEST_LEN 16
|
||||||
|
|
||||||
static int bpck_test_proto(struct pi_adapter *pi)
|
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];
|
char buf[TEST_LEN];
|
||||||
|
|
||||||
bpck_force_spp(pi);
|
bpck_force_spp(pi);
|
||||||
|
|
||||||
switch (pi->mode) {
|
switch (pi->mode) {
|
||||||
|
|
||||||
case 0: bpck_connect(pi);
|
case 0:
|
||||||
WR(0x13,0x7f);
|
bpck_connect(pi);
|
||||||
|
WR(0x13, 0x7f);
|
||||||
w0(0x13); t2(2);
|
w0(0x13); t2(2);
|
||||||
for(i=0;i<TEST_LEN;i++) {
|
for (i = 0; i < TEST_LEN; i++) {
|
||||||
t2(4); l = r1();
|
t2(4); l = r1();
|
||||||
t2(4); h = r1();
|
t2(4); h = r1();
|
||||||
buf[i] = j44(l,h);
|
buf[i] = j44(l, h);
|
||||||
}
|
}
|
||||||
bpck_disconnect(pi);
|
bpck_disconnect(pi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: bpck_connect(pi);
|
case 1:
|
||||||
WR(0x13,0x7f);
|
bpck_connect(pi);
|
||||||
w0(0x13); t2(2); t2(0x20);
|
WR(0x13, 0x7f);
|
||||||
for(i=0;i<TEST_LEN;i++) { t2(4); buf[i] = r0(); }
|
w0(0x13); t2(2); t2(0x20);
|
||||||
t2(1); t2(0x20);
|
for (i = 0; i < TEST_LEN; i++) {
|
||||||
|
t2(4);
|
||||||
|
buf[i] = r0();
|
||||||
|
}
|
||||||
|
t2(1); t2(0x20);
|
||||||
bpck_disconnect(pi);
|
bpck_disconnect(pi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
case 4: om = pi->mode;
|
case 4:
|
||||||
|
om = pi->mode;
|
||||||
pi->mode = 0;
|
pi->mode = 0;
|
||||||
bpck_connect(pi);
|
bpck_connect(pi);
|
||||||
WR(7,3);
|
WR(7, 3);
|
||||||
WR(4,8);
|
WR(4, 8);
|
||||||
bpck_disconnect(pi);
|
bpck_disconnect(pi);
|
||||||
|
|
||||||
pi->mode = om;
|
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);
|
w0(0x13); w2(9); w2(1); w0(0); w2(3); w2(0); w2(0xe0);
|
||||||
|
|
||||||
switch (pi->mode) {
|
switch (pi->mode) {
|
||||||
case 2: for (i=0;i<TEST_LEN;i++) buf[i] = r4();
|
case 2:
|
||||||
break;
|
for (i = 0; i < TEST_LEN; i++)
|
||||||
case 3: for (i=0;i<TEST_LEN/2;i++) ((u16 *)buf)[i] = r4w();
|
buf[i] = r4();
|
||||||
break;
|
break;
|
||||||
case 4: for (i=0;i<TEST_LEN/4;i++) ((u32 *)buf)[i] = r4l();
|
case 3:
|
||||||
break;
|
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);
|
w2(0);
|
||||||
WR(7,0);
|
WR(7, 0);
|
||||||
bpck_disconnect(pi);
|
bpck_disconnect(pi);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_dbg(&pi->dev, "bpck: 0x%x unit %d mode %d: ",
|
dev_dbg(&pi->dev, "bpck: 0x%x unit %d mode %d: ",
|
||||||
pi->port, pi->unit, pi->mode);
|
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;
|
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;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bpck_read_eeprom(struct pi_adapter *pi, char *buf)
|
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);
|
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;
|
pi->mode = 0; pi->delay = 6;
|
||||||
|
|
||||||
bpck_connect(pi);
|
bpck_connect(pi);
|
||||||
|
|
||||||
WR(4,0);
|
WR(4, 0);
|
||||||
for (i=0;i<64;i++) {
|
for (i = 0; i < 64; i++) {
|
||||||
WR(6,8);
|
WR(6, 8);
|
||||||
WR(6,0xc);
|
WR(6, 0xc);
|
||||||
p = 0x100;
|
p = 0x100;
|
||||||
for (k=0;k<9;k++) {
|
for (k = 0; k < 9; k++) {
|
||||||
f = (((i + 0x180) & p) != 0) * 2;
|
f = (((i + 0x180) & p) != 0) * 2;
|
||||||
WR(6,f+0xc);
|
WR(6, f + 0xc);
|
||||||
WR(6,f+0xd);
|
WR(6, f + 0xd);
|
||||||
WR(6,f+0xc);
|
WR(6, f + 0xc);
|
||||||
p = (p >> 1);
|
p = (p >> 1);
|
||||||
}
|
}
|
||||||
for (j=0;j<2;j++) {
|
for (j = 0; j < 2; j++) {
|
||||||
v = 0;
|
v = 0;
|
||||||
for (k=0;k<8;k++) {
|
for (k = 0; k < 8; k++) {
|
||||||
WR(6,0xc);
|
WR(6, 0xc);
|
||||||
WR(6,0xd);
|
WR(6, 0xd);
|
||||||
WR(6,0xc);
|
WR(6, 0xc);
|
||||||
f = RR(0);
|
f = RR(0);
|
||||||
v = 2*v + (f == 0x84);
|
v = 2 * v + (f == 0x84);
|
||||||
|
}
|
||||||
|
buf[2 * i + 1 - j] = v;
|
||||||
}
|
}
|
||||||
buf[2*i+1-j] = v;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
WR(6,8);
|
WR(6, 8);
|
||||||
WR(6,0);
|
WR(6, 0);
|
||||||
WR(5,8);
|
WR(5, 8);
|
||||||
|
|
||||||
bpck_disconnect(pi);
|
bpck_disconnect(pi);
|
||||||
|
|
||||||
if (om >= 2) {
|
if (om >= 2) {
|
||||||
bpck_connect(pi);
|
bpck_connect(pi);
|
||||||
WR(7,3);
|
WR(7, 3);
|
||||||
WR(4,8);
|
WR(4, 8);
|
||||||
bpck_disconnect(pi);
|
bpck_disconnect(pi);
|
||||||
}
|
}
|
||||||
|
|
||||||
pi->mode = om; pi->delay = od;
|
pi->mode = om; pi->delay = od;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bpck_test_port(struct pi_adapter *pi) /* check for 8-bit port */
|
static int bpck_test_port(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ int i, r, m;
|
int i, r, m;
|
||||||
|
|
||||||
|
/* Check for 8-bit port */
|
||||||
w2(0x2c); i = r0(); w0(255-i); r = r0(); w0(i);
|
w2(0x2c); i = r0(); w0(255-i); r = r0(); w0(i);
|
||||||
m = -1;
|
m = -1;
|
||||||
if (r == i) m = 2;
|
if (r == i)
|
||||||
if (r == (255-i)) m = 0;
|
m = 2;
|
||||||
|
if (r == (255-i))
|
||||||
|
m = 0;
|
||||||
|
|
||||||
w2(0xc); i = r0(); w0(255-i); r = r0(); w0(i);
|
w2(0xc);
|
||||||
if (r != (255-i)) m = -1;
|
i = r0();
|
||||||
|
w0(255-i);
|
||||||
if (m == 0) { w2(6); w2(0xc); r = r0(); w0(0xaa); w0(r); w0(0xaa); }
|
r = r0();
|
||||||
if (m == 2) { w2(0x26); w2(0xc); }
|
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;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bpck_log_adapter(struct pi_adapter *pi)
|
static void bpck_log_adapter(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ char *mode_string[5] = { "4-bit","8-bit","EPP-8",
|
char *mode_str[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
|
||||||
"EPP-16","EPP-32" };
|
|
||||||
char scratch[128];
|
char scratch[128];
|
||||||
|
|
||||||
bpck_read_eeprom(pi,scratch);
|
bpck_read_eeprom(pi,scratch);
|
||||||
print_hex_dump_bytes("bpck EEPROM: ", DUMP_PREFIX_NONE, scratch, 128);
|
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,
|
&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 = {
|
static struct pi_protocol bpck = {
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
/*
|
/*
|
||||||
backpack.c (c) 2001 Micro Solutions Inc.
|
* (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.c is a low-level protocol driver for the Micro Solutions
|
* "BACKPACK" parallel port IDE adapter (works on Series 6 drives).
|
||||||
"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)
|
||||||
Written by: Ken Hahn (linux-dev@micro-solutions.com)
|
*/
|
||||||
Clive Turvey (linux-dev@micro-solutions.com)
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -326,11 +324,14 @@ static int bpck6_open(struct pi_adapter *pi)
|
|||||||
if (j != k)
|
if (j != k)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
if (i & 4) // EPP
|
if (i & 4) {
|
||||||
|
/* EPP */
|
||||||
parport_frob_control(pi->pardev->port,
|
parport_frob_control(pi->pardev->port,
|
||||||
PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, 0);
|
PARPORT_CONTROL_SELECT | PARPORT_CONTROL_INIT, 0);
|
||||||
else // PPC/ECP
|
} else {
|
||||||
|
/* PPC/ECP */
|
||||||
parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, 0);
|
parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
pi->private = 0;
|
pi->private = 0;
|
||||||
|
|
||||||
@ -347,17 +348,20 @@ fail:
|
|||||||
parport_write_control(pi->pardev->port, pi->saved_r2);
|
parport_write_control(pi->pardev->port, pi->saved_r2);
|
||||||
parport_write_data(pi->pardev->port, pi->saved_r0);
|
parport_write_data(pi->pardev->port, pi->saved_r0);
|
||||||
|
|
||||||
return 0; // FAIL
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bpck6_deselect(struct pi_adapter *pi)
|
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_frob_control(pi->pardev->port, PARPORT_CONTROL_INIT,
|
||||||
PARPORT_CONTROL_INIT);
|
PARPORT_CONTROL_INIT);
|
||||||
else // PPC/ECP
|
} else {
|
||||||
|
/* PPC/ECP */
|
||||||
parport_frob_control(pi->pardev->port, PARPORT_CONTROL_SELECT,
|
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_data(pi->pardev->port, pi->saved_r0);
|
||||||
parport_write_control(pi->pardev->port,
|
parport_write_control(pi->pardev->port,
|
||||||
@ -386,7 +390,8 @@ static void bpck6_disconnect(struct pi_adapter *pi)
|
|||||||
bpck6_deselect(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",
|
dev_dbg(&pi->dev, "PARPORT indicates modes=%x for lp=0x%lx\n",
|
||||||
pi->pardev->port->modes, pi->pardev->port->base);
|
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);
|
dev_dbg(&pi->dev, "ppc_open returned %2x\n", out);
|
||||||
|
|
||||||
if(out)
|
if (out) {
|
||||||
{
|
|
||||||
bpck6_deselect(pi);
|
bpck6_deselect(pi);
|
||||||
dev_dbg(&pi->dev, "leaving probe\n");
|
dev_dbg(&pi->dev, "leaving probe\n");
|
||||||
pi->mode = saved_mode;
|
pi->mode = saved_mode;
|
||||||
return(1);
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
dev_dbg(&pi->dev, "Failed open\n");
|
||||||
dev_dbg(&pi->dev, "Failed open\n");
|
pi->mode = saved_mode;
|
||||||
pi->mode = saved_mode;
|
|
||||||
return(0);
|
return 0;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bpck6_log_adapter(struct pi_adapter *pi)
|
static void bpck6_log_adapter(struct pi_adapter *pi)
|
||||||
{
|
{
|
||||||
char *mode_string[5]=
|
char *mode_string[5] = { "4-bit", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
|
||||||
{"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",
|
dev_info(&pi->dev,
|
||||||
pi->unit, pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
"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 = {
|
static struct pi_protocol bpck6 = {
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
comm.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
/*
|
||||||
Under the terms of the GNU General Public License.
|
* (c) 1997-1998 Grant R. Guenther <grant@torque.net>
|
||||||
|
*
|
||||||
comm.c is a low-level protocol driver for some older models
|
* comm.c is a low-level protocol driver for some older models of the DataStor
|
||||||
of the DataStor "Commuter" parallel to IDE adapter. Some of
|
* "Commuter" parallel to IDE adapter. Some of the parallel port devices
|
||||||
the parallel port devices marketed by Arista currently
|
* marketed by Arista currently use this adapter.
|
||||||
use this adapter.
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -17,165 +16,172 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "pata_parport.h"
|
#include "pata_parport.h"
|
||||||
|
|
||||||
/* mode codes: 0 nybble reads, 8-bit writes
|
/*
|
||||||
1 8-bit reads and writes
|
* mode codes: 0 nybble reads, 8-bit writes
|
||||||
2 8-bit EPP mode
|
* 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 P1 w2(5);w2(0xd);w2(0xd);w2(5);w2(4);
|
||||||
#define P2 w2(5);w2(7);w2(7);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 cont_map[2] = { 0x08, 0x10 };
|
||||||
|
|
||||||
static int comm_read_regr(struct pi_adapter *pi, int cont, int regr)
|
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];
|
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);
|
case 1:
|
||||||
w2(6); l = r1(); w0(0x80); h = r1(); w2(4);
|
w0(r+0x20); P1;
|
||||||
return j44(l,h);
|
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 2:
|
||||||
case 3:
|
case 3:
|
||||||
case 4: w3(r+0x20); (void)r1();
|
case 4:
|
||||||
w2(0x24); h = r4(); w2(4);
|
w3(r+0x20); (void)r1();
|
||||||
return h;
|
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)
|
static void comm_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:
|
||||||
r = regr + cont_map[cont];
|
case 1:
|
||||||
|
w0(r); P1; w0(val); P2;
|
||||||
switch (pi->mode) {
|
|
||||||
|
|
||||||
case 0:
|
|
||||||
case 1: w0(r); P1; w0(val); P2;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
case 4: w3(r); (void)r1(); w4(val);
|
case 4:
|
||||||
break;
|
w3(r); (void)r1(); w4(val);
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void comm_connect(struct pi_adapter *pi)
|
static void comm_connect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ pi->saved_r0 = r0();
|
pi->saved_r0 = r0();
|
||||||
pi->saved_r2 = r2();
|
pi->saved_r2 = r2();
|
||||||
w2(4); w0(0xff); w2(6);
|
w2(4); w0(0xff); w2(6);
|
||||||
w2(4); w0(0xaa); w2(6);
|
w2(4); w0(0xaa); w2(6);
|
||||||
w2(4); w0(0x00); w2(6);
|
w2(4); w0(0x00); w2(6);
|
||||||
w2(4); w0(0x87); w2(6);
|
w2(4); w0(0x87); w2(6);
|
||||||
w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4);
|
w2(4); w0(0xe0); w2(0xc); w2(0xc); w2(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void comm_disconnect(struct pi_adapter *pi)
|
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);
|
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)
|
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:
|
||||||
switch (pi->mode) {
|
w0(0x48); P1;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
case 0: w0(0x48); P1;
|
w0(0); w2(6); l = r1();
|
||||||
for(i=0;i<count;i++) {
|
w0(0x80); h = r1(); w2(4);
|
||||||
w0(0); w2(6); l = r1();
|
buf[i] = j44(l, h);
|
||||||
w0(0x80); h = r1(); w2(4);
|
}
|
||||||
buf[i] = j44(l,h);
|
break;
|
||||||
}
|
case 1:
|
||||||
break;
|
w0(0x68); P1; w0(0);
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
case 1: w0(0x68); P1; w0(0);
|
w2(0x26);
|
||||||
for(i=0;i<count;i++) {
|
buf[i] = r0();
|
||||||
w2(0x26); buf[i] = r0(); w2(0x24);
|
w2(0x24);
|
||||||
}
|
}
|
||||||
w2(4);
|
w2(4);
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
case 2: w3(0x68); (void)r1(); w2(0x24);
|
w3(0x68); (void)r1(); w2(0x24);
|
||||||
for (i=0;i<count;i++) buf[i] = r4();
|
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);
|
w2(4);
|
||||||
break;
|
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 ! */
|
/* NB: Watch out for the byte swapped writes ! */
|
||||||
|
|
||||||
static void comm_write_block(struct pi_adapter *pi, char *buf, int count)
|
static void comm_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
{ int k;
|
switch (pi->mode) {
|
||||||
|
case 0:
|
||||||
switch (pi->mode) {
|
case 1:
|
||||||
|
w0(0x68); P1;
|
||||||
case 0:
|
for (k = 0; k < count; k++) {
|
||||||
case 1: w0(0x68); P1;
|
w2(5);
|
||||||
for (k=0;k<count;k++) {
|
w0(buf[k ^ 1]);
|
||||||
w2(5); w0(buf[k^1]); w2(7);
|
w2(7);
|
||||||
}
|
}
|
||||||
w2(5); w2(4);
|
w2(5); w2(4);
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
case 2: w3(0x48); (void)r1();
|
w3(0x48); (void)r1();
|
||||||
for (k=0;k<count;k++) w4(buf[k^1]);
|
for (k = 0; k < count; k++)
|
||||||
break;
|
w4(buf[k ^ 1]);
|
||||||
|
break;
|
||||||
case 3: w3(0x48); (void)r1();
|
case 3:
|
||||||
|
w3(0x48); (void)r1();
|
||||||
for (k = 0; k < count / 2; k++)
|
for (k = 0; k < count / 2; k++)
|
||||||
w4w(swab16(((u16 *)buf)[k]));
|
w4w(swab16(((u16 *)buf)[k]));
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
case 4: w3(0x48); (void)r1();
|
w3(0x48); (void)r1();
|
||||||
for (k = 0; k < count / 4; k++)
|
for (k = 0; k < count / 4; k++)
|
||||||
w4l(swab16(((u16 *)buf)[2 * k]) |
|
w4l(swab16(((u16 *)buf)[2 * k]) |
|
||||||
swab16(((u16 *)buf)[2 * k + 1]) << 16);
|
swab16(((u16 *)buf)[2 * k + 1]) << 16);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void comm_log_adapter(struct pi_adapter *pi)
|
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",
|
dev_info(&pi->dev,
|
||||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
"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 = {
|
static struct pi_protocol comm = {
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
dstr.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
/*
|
||||||
Under the terms of the GNU General Public License.
|
* (c) 1997-1998 Grant R. Guenther <grant@torque.net>
|
||||||
|
*
|
||||||
dstr.c is a low-level protocol driver for the
|
* dstr.c is a low-level protocol driver for the DataStor EP2000 parallel
|
||||||
DataStor EP2000 parallel to IDE adapter chip.
|
* to IDE adapter chip.
|
||||||
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -16,178 +15,202 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "pata_parport.h"
|
#include "pata_parport.h"
|
||||||
|
|
||||||
/* mode codes: 0 nybble reads, 8-bit writes
|
/*
|
||||||
1 8-bit reads and writes
|
* mode codes: 0 nybble reads, 8-bit writes
|
||||||
2 8-bit EPP mode
|
* 1 8-bit reads and writes
|
||||||
3 EPP-16
|
* 2 8-bit EPP mode
|
||||||
4 EPP-32
|
* 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 P1 w2(5);w2(0xd);w2(5);w2(4);
|
||||||
#define P2 w2(5);w2(7);w2(5);w2(4);
|
#define P2 w2(5);w2(7);w2(5);w2(4);
|
||||||
#define P3 w2(6);w2(4);w2(6);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 cont_map[2] = { 0x20, 0x40 };
|
||||||
|
|
||||||
static int dstr_read_regr(struct pi_adapter *pi, int cont, int regr)
|
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;
|
w0(0x81); P1;
|
||||||
if (pi->mode) { w0(0x11); } else { w0(1); }
|
if (pi->mode)
|
||||||
|
w0(0x11);
|
||||||
|
else
|
||||||
|
w0(1);
|
||||||
P2; w0(r); P1;
|
P2; w0(r); P1;
|
||||||
|
|
||||||
switch (pi->mode) {
|
switch (pi->mode) {
|
||||||
|
case 0:
|
||||||
case 0: w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4);
|
w2(6); a = r1(); w2(4); w2(6); b = r1(); w2(4);
|
||||||
return j44(a,b);
|
return j44(a, b);
|
||||||
|
case 1:
|
||||||
case 1: w0(0); w2(0x26); a = r0(); w2(4);
|
w0(0); w2(0x26); a = r0(); w2(4);
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
case 4: w2(0x24); a = r4(); w2(4);
|
case 4:
|
||||||
return a;
|
w2(0x24); a = r4(); w2(4);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
return -1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CCP(x) w0(0xff);w2(0xc);w2(4);\
|
static void dstr_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||||
w0(0xaa);w0(0x55);w0(0);w0(0xff);w0(0x87);w0(0x78);\
|
{
|
||||||
w0(x);w2(5);w2(4);
|
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)
|
static void dstr_connect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ pi->saved_r0 = r0();
|
pi->saved_r0 = r0();
|
||||||
pi->saved_r2 = r2();
|
pi->saved_r2 = r2();
|
||||||
w2(4); CCP(0xe0); w0(0xff);
|
w2(4); CCP(0xe0); w0(0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dstr_disconnect(struct pi_adapter *pi)
|
static void dstr_disconnect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ CCP(0x30);
|
CCP(0x30);
|
||||||
w0(pi->saved_r0);
|
w0(pi->saved_r0);
|
||||||
w2(pi->saved_r2);
|
w2(pi->saved_r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dstr_read_block(struct pi_adapter *pi, char *buf, int count)
|
static void dstr_read_block(struct pi_adapter *pi, char *buf, int count)
|
||||||
|
{
|
||||||
{ int k, a, b;
|
int k, a, b;
|
||||||
|
|
||||||
w0(0x81); P1;
|
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;
|
P2; w0(0x82); P1; P3; w0(0x20); P1;
|
||||||
|
|
||||||
switch (pi->mode) {
|
switch (pi->mode) {
|
||||||
|
case 0:
|
||||||
case 0: for (k=0;k<count;k++) {
|
for (k = 0; k < count; k++) {
|
||||||
w2(6); a = r1(); w2(4);
|
w2(6); a = r1(); w2(4);
|
||||||
w2(6); b = r1(); w2(4);
|
w2(6); b = r1(); w2(4);
|
||||||
buf[k] = j44(a,b);
|
buf[k] = j44(a, b);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 1:
|
||||||
case 1: w0(0);
|
w0(0);
|
||||||
for (k=0;k<count;k++) {
|
for (k = 0; k < count; k++) {
|
||||||
w2(0x26); buf[k] = r0(); w2(0x24);
|
w2(0x26);
|
||||||
}
|
buf[k] = r0();
|
||||||
w2(4);
|
w2(0x24);
|
||||||
break;
|
}
|
||||||
|
w2(4);
|
||||||
case 2: w2(0x24);
|
break;
|
||||||
for (k=0;k<count;k++) buf[k] = r4();
|
case 2:
|
||||||
w2(4);
|
w2(0x24);
|
||||||
break;
|
for (k = 0; k < count; k++)
|
||||||
|
buf[k] = r4();
|
||||||
case 3: w2(0x24);
|
w2(4);
|
||||||
for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
|
break;
|
||||||
w2(4);
|
case 3:
|
||||||
break;
|
w2(0x24);
|
||||||
|
for (k = 0; k < count / 2; k++)
|
||||||
case 4: w2(0x24);
|
((u16 *)buf)[k] = r4w();
|
||||||
for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
|
w2(4);
|
||||||
w2(4);
|
break;
|
||||||
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)
|
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;
|
switch (pi->mode) {
|
||||||
if (pi->mode) { w0(0x19); } else { w0(9); }
|
case 0:
|
||||||
P2; w0(0x82); P1; P3; w0(0x20); P1;
|
case 1:
|
||||||
|
for (k = 0; k < count; k++) {
|
||||||
switch (pi->mode) {
|
w2(5);
|
||||||
|
w0(buf[k]);
|
||||||
case 0:
|
w2(7);
|
||||||
case 1: for (k=0;k<count;k++) {
|
}
|
||||||
w2(5); w0(buf[k]); w2(7);
|
w2(5); w2(4);
|
||||||
}
|
break;
|
||||||
w2(5); w2(4);
|
case 2:
|
||||||
break;
|
w2(0xc5);
|
||||||
|
for (k = 0; k < count; k++)
|
||||||
case 2: w2(0xc5);
|
w4(buf[k]);
|
||||||
for (k=0;k<count;k++) w4(buf[k]);
|
|
||||||
w2(0xc4);
|
w2(0xc4);
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
case 3: w2(0xc5);
|
w2(0xc5);
|
||||||
for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
|
for (k = 0; k < count / 2; k++)
|
||||||
w2(0xc4);
|
w4w(((u16 *)buf)[k]);
|
||||||
break;
|
w2(0xc4);
|
||||||
|
break;
|
||||||
case 4: w2(0xc5);
|
case 4:
|
||||||
for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
|
w2(0xc5);
|
||||||
w2(0xc4);
|
for (k = 0; k < count / 4; k++)
|
||||||
break;
|
w4l(((u32 *)buf)[k]);
|
||||||
|
w2(0xc4);
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void dstr_log_adapter(struct pi_adapter *pi)
|
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",
|
dev_info(&pi->dev,
|
||||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
"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 = {
|
static struct pi_protocol dstr = {
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
epat.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
/*
|
||||||
Under the terms of the GNU General Public License.
|
* (c) 1997-1998 Grant R. Guenther <grant@torque.net>
|
||||||
|
*
|
||||||
This is the low level protocol driver for the EPAT parallel
|
* This is the low level protocol driver for the EPAT parallel
|
||||||
to IDE adapter from Shuttle Technologies. This adapter is
|
* to IDE adapter from Shuttle Technologies. This adapter is
|
||||||
used in many popular parallel port disk products such as the
|
* used in many popular parallel port disk products such as the
|
||||||
SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk.
|
* SyQuest EZ drives, the Avatar Shark and the Imation SuperDisk.
|
||||||
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -18,276 +17,313 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "pata_parport.h"
|
#include "pata_parport.h"
|
||||||
|
|
||||||
#define j44(a,b) (((a>>4)&0x0f)+(b&0xf0))
|
#define j44(a, b) (((a >> 4) & 0x0f) + (b & 0xf0))
|
||||||
#define j53(a,b) (((a>>3)&0x1f)+((b<<4)&0xe0))
|
#define j53(a, b) (((a >> 3) & 0x1f) + ((b << 4) & 0xe0))
|
||||||
|
|
||||||
static int epatc8;
|
static int epatc8;
|
||||||
|
|
||||||
module_param(epatc8, int, 0);
|
module_param(epatc8, int, 0);
|
||||||
MODULE_PARM_DESC(epatc8, "support for the Shuttle EP1284 chip, "
|
MODULE_PARM_DESC(epatc8,
|
||||||
"used in any recent Imation SuperDisk (LS-120) drive.");
|
"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
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cont = 0 IDE register file
|
||||||
|
* cont = 1 IDE control registers
|
||||||
|
* cont = 2 internal EPAT registers
|
||||||
|
*/
|
||||||
static int cont_map[3] = { 0x18, 0x10, 0 };
|
static int cont_map[3] = { 0x18, 0x10, 0 };
|
||||||
|
|
||||||
static void epat_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
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];
|
r = regr + cont_map[cont];
|
||||||
|
|
||||||
switch (pi->mode) {
|
switch (pi->mode) {
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
w0(r); w2(1); w2(3);
|
||||||
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);
|
|
||||||
a = r1(); w2(4); b = r1();
|
a = r1(); w2(4); b = r1();
|
||||||
return j44(a,b);
|
return j44(a, b);
|
||||||
|
case 1:
|
||||||
case 1: w0(0x40+r); w2(1); w2(4);
|
w0(0x40+r); w2(1); w2(4);
|
||||||
a = r1(); b = r2(); w0(0xff);
|
a = r1(); b = r2(); w0(0xff);
|
||||||
return j53(a,b);
|
return j53(a, b);
|
||||||
|
case 2:
|
||||||
case 2: w0(0x20+r); w2(1); w2(0x25);
|
w0(0x20+r); w2(1); w2(0x25);
|
||||||
a = r0(); w2(4);
|
a = r0(); w2(4);
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
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 a;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1; /* never gets here */
|
return -1; /* never gets here */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void epat_read_block(struct pi_adapter *pi, char *buf, int count)
|
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) {
|
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;
|
ph = 0;
|
||||||
for(k=0;k<count;k++) {
|
for (k = 0; k < count; k++) {
|
||||||
if (k == count-1) w0(0xfd);
|
if (k == count-1)
|
||||||
w2(6+ph); a = r1();
|
w0(0xfd);
|
||||||
if (a & 8) b = a;
|
w2(6 + ph); a = r1();
|
||||||
else { w2(4+ph); b = r1(); }
|
if (a & 8) {
|
||||||
buf[k] = j44(a,b);
|
b = a;
|
||||||
|
} else {
|
||||||
|
w2(4+ph); b = r1();
|
||||||
|
}
|
||||||
|
buf[k] = j44(a, b);
|
||||||
ph = 1 - ph;
|
ph = 1 - ph;
|
||||||
}
|
}
|
||||||
w0(0); w2(4);
|
w0(0); w2(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: w0(0x47); w2(1); w2(5); w0(0xff);
|
case 1:
|
||||||
|
w0(0x47); w2(1); w2(5); w0(0xff);
|
||||||
ph = 0;
|
ph = 0;
|
||||||
for(k=0;k<count;k++) {
|
for (k = 0; k < count; k++) {
|
||||||
if (k == count-1) w0(0xfd);
|
if (k == count - 1)
|
||||||
w2(4+ph);
|
w0(0xfd);
|
||||||
|
w2(4 + ph);
|
||||||
a = r1(); b = r2();
|
a = r1(); b = r2();
|
||||||
buf[k] = j53(a,b);
|
buf[k] = j53(a, b);
|
||||||
ph = 1 - ph;
|
ph = 1 - ph;
|
||||||
}
|
}
|
||||||
w0(0); w2(4);
|
w0(0); w2(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: w0(0x27); w2(1); w2(0x25); w0(0);
|
case 2:
|
||||||
|
w0(0x27); w2(1); w2(0x25); w0(0);
|
||||||
ph = 0;
|
ph = 0;
|
||||||
for(k=0;k<count-1;k++) {
|
for (k = 0; k < count - 1; k++) {
|
||||||
w2(0x24+ph);
|
w2(0x24 + ph);
|
||||||
buf[k] = r0();
|
buf[k] = r0();
|
||||||
ph = 1 - ph;
|
ph = 1 - ph;
|
||||||
}
|
}
|
||||||
w2(0x26); w2(0x27); buf[count-1] = r0();
|
w2(0x26); w2(0x27);
|
||||||
|
buf[count - 1] = r0();
|
||||||
w2(0x25); w2(4);
|
w2(0x25); w2(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: w3(0x80); w2(0x24);
|
case 3:
|
||||||
for(k=0;k<count-1;k++) buf[k] = r4();
|
w3(0x80); w2(0x24);
|
||||||
w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
|
for (k = 0; k < count - 1; k++)
|
||||||
|
buf[k] = r4();
|
||||||
|
w2(4); w3(0xa0); w2(0x24);
|
||||||
|
buf[count - 1] = r4();
|
||||||
w2(4);
|
w2(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: w3(0x80); w2(0x24);
|
case 4:
|
||||||
for(k=0;k<(count/2)-1;k++) ((u16 *)buf)[k] = r4w();
|
w3(0x80); w2(0x24);
|
||||||
buf[count-2] = r4();
|
for (k = 0; k < count / 2 - 1; k++)
|
||||||
w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
|
((u16 *)buf)[k] = r4w();
|
||||||
|
buf[count - 2] = r4();
|
||||||
|
w2(4); w3(0xa0); w2(0x24);
|
||||||
|
buf[count - 1] = r4();
|
||||||
w2(4);
|
w2(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5: w3(0x80); w2(0x24);
|
case 5:
|
||||||
for(k=0;k<(count/4)-1;k++) ((u32 *)buf)[k] = r4l();
|
w3(0x80); w2(0x24);
|
||||||
for(k=count-4;k<count-1;k++) buf[k] = r4();
|
for (k = 0; k < count / 4 - 1; k++)
|
||||||
w2(4); w3(0xa0); w2(0x24); buf[count-1] = r4();
|
((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);
|
w2(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void epat_write_block(struct pi_adapter *pi, char *buf, int count)
|
static void epat_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||||
|
{
|
||||||
{ int ph, k;
|
int ph, k;
|
||||||
|
|
||||||
switch (pi->mode) {
|
switch (pi->mode) {
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
case 1:
|
||||||
case 2: w0(0x67); w2(1); w2(5);
|
case 2:
|
||||||
|
w0(0x67); w2(1); w2(5);
|
||||||
ph = 0;
|
ph = 0;
|
||||||
for(k=0;k<count;k++) {
|
for (k = 0; k < count; k++) {
|
||||||
w0(buf[k]);
|
w0(buf[k]);
|
||||||
w2(4+ph);
|
w2(4 + ph);
|
||||||
ph = 1 - ph;
|
ph = 1 - ph;
|
||||||
}
|
}
|
||||||
w2(7); w2(4);
|
w2(7); w2(4);
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
case 3: w3(0xc0);
|
w3(0xc0);
|
||||||
for(k=0;k<count;k++) w4(buf[k]);
|
for (k = 0; k < count; k++)
|
||||||
|
w4(buf[k]);
|
||||||
w2(4);
|
w2(4);
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
case 4: w3(0xc0);
|
w3(0xc0);
|
||||||
for(k=0;k<(count/2);k++) w4w(((u16 *)buf)[k]);
|
for (k = 0; k < count / 2; k++)
|
||||||
|
w4w(((u16 *)buf)[k]);
|
||||||
w2(4);
|
w2(4);
|
||||||
break;
|
break;
|
||||||
|
case 5:
|
||||||
case 5: w3(0xc0);
|
w3(0xc0);
|
||||||
for(k=0;k<(count/4);k++) w4l(((u32 *)buf)[k]);
|
for (k = 0; k < count / 4; k++)
|
||||||
|
w4l(((u32 *)buf)[k]);
|
||||||
w2(4);
|
w2(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* these macros access the EPAT registers in native addressing */
|
/* these macros access the EPAT registers in native addressing */
|
||||||
|
|
||||||
#define WR(r,v) epat_write_regr(pi,2,r,v)
|
#define WR(r, v) epat_write_regr(pi, 2, r, v)
|
||||||
#define RR(r) (epat_read_regr(pi,2,r))
|
#define RR(r) epat_read_regr(pi, 2, r)
|
||||||
|
|
||||||
/* and these access the IDE task file */
|
/* and these access the IDE task file */
|
||||||
|
|
||||||
#define WRi(r,v) epat_write_regr(pi,0,r,v)
|
#define WRi(r, v) epat_write_regr(pi, 0, r, v)
|
||||||
#define RRi(r) (epat_read_regr(pi,0,r))
|
#define RRi(r) epat_read_regr(pi, 0, r)
|
||||||
|
|
||||||
/* FIXME: the CPP stuff should be fixed to handle multiple EPATs on a chain */
|
/* 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);\
|
#define CPP(x) \
|
||||||
w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
|
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)
|
static void epat_connect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ pi->saved_r0 = r0();
|
pi->saved_r0 = r0();
|
||||||
pi->saved_r2 = r2();
|
pi->saved_r2 = r2();
|
||||||
|
|
||||||
/* Initialize the chip */
|
/* Initialize the chip */
|
||||||
CPP(0);
|
CPP(0);
|
||||||
|
|
||||||
if (epatc8) {
|
if (epatc8) {
|
||||||
CPP(0x40);CPP(0xe0);
|
CPP(0x40); CPP(0xe0);
|
||||||
w0(0);w2(1);w2(4);
|
w0(0); w2(1); w2(4);
|
||||||
WR(0x8,0x12);WR(0xc,0x14);WR(0x12,0x10);
|
WR(0x8, 0x12);
|
||||||
WR(0xe,0xf);WR(0xf,4);
|
WR(0xc, 0x14);
|
||||||
|
WR(0x12, 0x10);
|
||||||
|
WR(0xe, 0xf);
|
||||||
|
WR(0xf, 4);
|
||||||
/* WR(0xe,0xa);WR(0xf,4); */
|
/* WR(0xe,0xa);WR(0xf,4); */
|
||||||
WR(0xe,0xd);WR(0xf,0);
|
WR(0xe, 0xd);
|
||||||
|
WR(0xf, 0);
|
||||||
/* CPP(0x30); */
|
/* CPP(0x30); */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connect to the chip */
|
/* Connect to the chip */
|
||||||
CPP(0xe0);
|
CPP(0xe0);
|
||||||
w0(0);w2(1);w2(4); /* Idle into SPP */
|
w0(0); w2(1); w2(4); /* Idle into SPP */
|
||||||
if (pi->mode >= 3) {
|
if (pi->mode >= 3) {
|
||||||
w0(0);w2(1);w2(4);w2(0xc);
|
w0(0); w2(1); w2(4); w2(0xc);
|
||||||
/* Request EPP */
|
/* Request EPP */
|
||||||
w0(0x40);w2(6);w2(7);w2(4);w2(0xc);w2(4);
|
w0(0x40); w2(6); w2(7); w2(4); w2(0xc); w2(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!epatc8) {
|
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)
|
static void epat_disconnect(struct pi_adapter *pi)
|
||||||
{ CPP(0x30);
|
{
|
||||||
|
CPP(0x30);
|
||||||
w0(pi->saved_r0);
|
w0(pi->saved_r0);
|
||||||
w2(pi->saved_r2);
|
w2(pi->saved_r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int epat_test_proto(struct pi_adapter *pi)
|
static int epat_test_proto(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ int k, j, f, cc;
|
int k, j, f, cc;
|
||||||
int e[2] = {0,0};
|
int e[2] = { 0, 0 };
|
||||||
char scratch[512];
|
char scratch[512];
|
||||||
|
|
||||||
epat_connect(pi);
|
epat_connect(pi);
|
||||||
cc = RR(0xd);
|
cc = RR(0xd);
|
||||||
epat_disconnect(pi);
|
epat_disconnect(pi);
|
||||||
|
|
||||||
epat_connect(pi);
|
epat_connect(pi);
|
||||||
for (j=0;j<2;j++) {
|
for (j=0;j<2;j++) {
|
||||||
WRi(6,0xa0+j*0x10);
|
WRi(6, 0xa0 + j * 0x10);
|
||||||
for (k=0;k<256;k++) {
|
for (k = 0; k < 256; k++) {
|
||||||
WRi(2,k^0xaa);
|
WRi(2, k ^ 0xaa);
|
||||||
WRi(3,k^0x55);
|
WRi(3, k ^ 0x55);
|
||||||
if (RRi(2) != (k^0xaa)) e[j]++;
|
if (RRi(2) != (k ^ 0xaa))
|
||||||
}
|
e[j]++;
|
||||||
}
|
}
|
||||||
epat_disconnect(pi);
|
}
|
||||||
|
epat_disconnect(pi);
|
||||||
|
|
||||||
f = 0;
|
f = 0;
|
||||||
epat_connect(pi);
|
epat_connect(pi);
|
||||||
WR(0x13,1); WR(0x13,0); WR(0xa,0x11);
|
WR(0x13, 1); WR(0x13, 0); WR(0xa, 0x11);
|
||||||
epat_read_block(pi,scratch,512);
|
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);
|
|
||||||
|
|
||||||
dev_dbg(&pi->dev, "epat: port 0x%x, mode %d, ccr %x, test=(%d,%d,%d)\n",
|
for (k = 0; k < 256; k++) {
|
||||||
pi->port, pi->mode, cc, e[0], e[1], f);
|
if ((scratch[2 * k] & 0xff) != k)
|
||||||
|
f++;
|
||||||
return (e[0] && e[1]) || 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)
|
static void epat_log_adapter(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ int ver;
|
int ver;
|
||||||
char *mode_string[6] =
|
char *mode_string[6] =
|
||||||
{"4-bit","5/3","8-bit","EPP-8","EPP-16","EPP-32"};
|
{ "4-bit", "5/3", "8-bit", "EPP-8", "EPP-16", "EPP-32" };
|
||||||
|
|
||||||
epat_connect(pi);
|
epat_connect(pi);
|
||||||
WR(0xa,0x38); /* read the version code */
|
WR(0xa, 0x38); /* read the version code */
|
||||||
ver = RR(0xb);
|
ver = RR(0xb);
|
||||||
epat_disconnect(pi);
|
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);
|
ver, pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
epia.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
/*
|
||||||
Under the terms of the GNU General Public License.
|
* (c) 1997-1998 Grant R. Guenther <grant@torque.net>
|
||||||
|
*
|
||||||
epia.c is a low-level protocol driver for Shuttle Technologies
|
* epia.c is a low-level protocol driver for Shuttle Technologies
|
||||||
EPIA parallel to IDE adapter chip. This device is now obsolete
|
* EPIA parallel to IDE adapter chip. This device is now obsolete
|
||||||
and has been replaced with the EPAT chip, which is supported
|
* and has been replaced with the EPAT chip, which is supported
|
||||||
by epat.c, however, some devices based on EPIA are still
|
* by epat.c, however, some devices based on EPIA are still
|
||||||
available.
|
* available.
|
||||||
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -19,255 +18,274 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "pata_parport.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
|
* mode codes: 0 nybble reads on port 1, 8-bit writes
|
||||||
2 8-bit reads and writes
|
* 1 5/3 reads on ports 1 & 2, 8-bit writes
|
||||||
3 8-bit EPP mode
|
* 2 8-bit reads and writes
|
||||||
4 16-bit EPP
|
* 3 8-bit EPP mode
|
||||||
5 32-bit EPP
|
* 4 16-bit EPP
|
||||||
*/
|
* 5 32-bit EPP
|
||||||
|
*/
|
||||||
|
|
||||||
#define j44(a,b) (((a>>4)&0x0f)+(b&0xf0))
|
#define j44(a, b) (((a >> 4) & 0x0f) + (b & 0xf0))
|
||||||
#define j53(a,b) (((a>>3)&0x1f)+((b<<4)&0xe0))
|
#define j53(a, b) (((a >> 3) & 0x1f) + ((b << 4) & 0xe0))
|
||||||
|
|
||||||
/* cont = 0 IDE register file
|
|
||||||
cont = 1 IDE control registers
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* cont = 0 IDE register file
|
||||||
|
* cont = 1 IDE control registers
|
||||||
|
*/
|
||||||
static int cont_map[2] = { 0, 0x80 };
|
static int cont_map[2] = { 0, 0x80 };
|
||||||
|
|
||||||
static int epia_read_regr(struct pi_adapter *pi, int cont, int regr)
|
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];
|
regr += cont_map[cont];
|
||||||
|
|
||||||
switch (pi->mode) {
|
switch (pi->mode) {
|
||||||
|
case 0:
|
||||||
case 0: r = regr^0x39;
|
r = regr ^ 0x39;
|
||||||
w0(r); w2(1); w2(3); w0(r);
|
w0(r); w2(1); w2(3); w0(r);
|
||||||
a = r1(); w2(1); b = r1(); w2(4);
|
a = r1(); w2(1); b = r1(); w2(4);
|
||||||
return j44(a,b);
|
return j44(a, b);
|
||||||
|
case 1:
|
||||||
case 1: r = regr^0x31;
|
r = regr ^ 0x31;
|
||||||
w0(r); w2(1); w0(r&0x37);
|
w0(r); w2(1); w0(r & 0x37);
|
||||||
w2(3); w2(5); w0(r|0xf0);
|
w2(3); w2(5); w0(r | 0xf0);
|
||||||
a = r1(); b = r2(); w2(4);
|
a = r1(); b = r2(); w2(4);
|
||||||
return j53(a,b);
|
return j53(a, b);
|
||||||
|
case 2:
|
||||||
case 2: r = regr^0x29;
|
r = regr^0x29;
|
||||||
w0(r); w2(1); w2(0X21); w2(0x23);
|
w0(r); w2(1); w2(0X21); w2(0x23);
|
||||||
a = r0(); w2(4);
|
a = r0(); w2(4);
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
case 5: w3(regr); w2(0x24); a = r4(); w2(4);
|
case 5:
|
||||||
return a;
|
w3(regr); w2(0x24); a = r4(); w2(4);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
return -1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WR(r,v) epia_write_regr(pi,0,r,v)
|
static void epia_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||||
#define RR(r) (epia_read_regr(pi,0,r))
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
/* The use of register 0x84 is entirely unclear - it seems to control
|
regr += cont_map[cont];
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
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)
|
static void epia_connect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
|
pi->saved_r0 = r0();
|
||||||
|
pi->saved_r2 = r2();
|
||||||
|
|
||||||
{ pi->saved_r0 = r0();
|
w2(4); w0(0xa0); w0(0x50); w0(0xc0); w0(0x30); w0(0xa0); w0(0);
|
||||||
pi->saved_r2 = r2();
|
w2(1); w2(4);
|
||||||
|
if (pi->mode >= 3) {
|
||||||
w2(4); w0(0xa0); w0(0x50); w0(0xc0); w0(0x30); w0(0xa0); w0(0);
|
w0(0xa); w2(1); w2(4); w0(0x82); w2(4); w2(0xc); w2(4);
|
||||||
w2(1); w2(4);
|
w2(0x24); w2(0x26); w2(4);
|
||||||
if (pi->mode >= 3) {
|
}
|
||||||
w0(0xa); w2(1); w2(4); w0(0x82); w2(4); w2(0xc); w2(4);
|
WR(0x86, 8);
|
||||||
w2(0x24); w2(0x26); w2(4);
|
|
||||||
}
|
|
||||||
WR(0x86,8);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void epia_disconnect(struct pi_adapter *pi)
|
static void epia_disconnect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ /* WR(0x84,0x10); */
|
/* WR(0x84,0x10); */
|
||||||
w0(pi->saved_r0);
|
w0(pi->saved_r0);
|
||||||
w2(1); w2(4);
|
w2(1); w2(4);
|
||||||
w0(pi->saved_r0);
|
w0(pi->saved_r0);
|
||||||
w2(pi->saved_r2);
|
w2(pi->saved_r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void epia_read_block(struct pi_adapter *pi, char *buf, int count)
|
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) {
|
switch (pi->mode) {
|
||||||
|
case 0:
|
||||||
case 0: w0(0x81); w2(1); w2(3); w0(0xc1);
|
w0(0x81); w2(1); w2(3); w0(0xc1);
|
||||||
ph = 1;
|
ph = 1;
|
||||||
for (k=0;k<count;k++) {
|
for (k = 0; k < count; k++) {
|
||||||
w2(2+ph); a = r1();
|
w2(2+ph); a = r1();
|
||||||
w2(4+ph); b = r1();
|
w2(4+ph); b = r1();
|
||||||
buf[k] = j44(a,b);
|
buf[k] = j44(a, b);
|
||||||
ph = 1 - ph;
|
ph = 1 - ph;
|
||||||
}
|
}
|
||||||
w0(0); w2(4);
|
w0(0); w2(4);
|
||||||
break;
|
break;
|
||||||
|
case 1:
|
||||||
case 1: w0(0x91); w2(1); w0(0x10); w2(3);
|
w0(0x91); w2(1); w0(0x10); w2(3);
|
||||||
w0(0x51); w2(5); w0(0xd1);
|
w0(0x51); w2(5); w0(0xd1);
|
||||||
ph = 1;
|
ph = 1;
|
||||||
for (k=0;k<count;k++) {
|
for (k = 0; k < count; k++) {
|
||||||
w2(4+ph);
|
w2(4 + ph);
|
||||||
a = r1(); b = r2();
|
a = r1(); b = r2();
|
||||||
buf[k] = j53(a,b);
|
buf[k] = j53(a, b);
|
||||||
ph = 1 - ph;
|
ph = 1 - ph;
|
||||||
}
|
}
|
||||||
w0(0); w2(4);
|
w0(0); w2(4);
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
case 2: w0(0x89); w2(1); w2(0x23); w2(0x21);
|
w0(0x89); w2(1); w2(0x23); w2(0x21);
|
||||||
ph = 1;
|
ph = 1;
|
||||||
for (k=0;k<count;k++) {
|
for (k = 0; k < count; k++) {
|
||||||
w2(0x24+ph);
|
w2(0x24 + ph);
|
||||||
buf[k] = r0();
|
buf[k] = r0();
|
||||||
ph = 1 - ph;
|
ph = 1 - ph;
|
||||||
}
|
}
|
||||||
w2(6); w2(4);
|
w2(6); w2(4);
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
case 3: if (count > 512) WR(0x84,3);
|
if (count > 512)
|
||||||
|
WR(0x84, 3);
|
||||||
w3(0); w2(0x24);
|
w3(0); w2(0x24);
|
||||||
for (k=0;k<count;k++) buf[k] = r4();
|
for (k = 0; k < count; k++)
|
||||||
w2(4); WR(0x84,0);
|
buf[k] = r4();
|
||||||
break;
|
w2(4); WR(0x84, 0);
|
||||||
|
break;
|
||||||
case 4: if (count > 512) WR(0x84,3);
|
case 4:
|
||||||
|
if (count > 512)
|
||||||
|
WR(0x84, 3);
|
||||||
w3(0); w2(0x24);
|
w3(0); w2(0x24);
|
||||||
for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
|
for (k = 0; k < count / 2; k++)
|
||||||
w2(4); WR(0x84,0);
|
((u16 *)buf)[k] = r4w();
|
||||||
break;
|
w2(4); WR(0x84, 0);
|
||||||
|
break;
|
||||||
case 5: if (count > 512) WR(0x84,3);
|
case 5:
|
||||||
|
if (count > 512)
|
||||||
|
WR(0x84, 3);
|
||||||
w3(0); w2(0x24);
|
w3(0); w2(0x24);
|
||||||
for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
|
for (k = 0; k < count / 4; k++)
|
||||||
w2(4); WR(0x84,0);
|
((u32 *)buf)[k] = r4l();
|
||||||
break;
|
w2(4); WR(0x84, 0);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void epia_write_block(struct pi_adapter *pi, char *buf, int count)
|
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:
|
||||||
switch (pi->mode) {
|
case 1:
|
||||||
|
case 2:
|
||||||
case 0:
|
w0(0xa1); w2(1); w2(3); w2(1); w2(5);
|
||||||
case 1:
|
ph = 0; last = 0x8000;
|
||||||
case 2: w0(0xa1); w2(1); w2(3); w2(1); w2(5);
|
for (k = 0; k < count; k++) {
|
||||||
ph = 0; last = 0x8000;
|
d = buf[k];
|
||||||
for (k=0;k<count;k++) {
|
if (d != last) {
|
||||||
d = buf[k];
|
last = d;
|
||||||
if (d != last) { last = d; w0(d); }
|
w0(d);
|
||||||
w2(4+ph);
|
}
|
||||||
ph = 1 - ph;
|
w2(4 + ph);
|
||||||
}
|
ph = 1 - ph;
|
||||||
w2(7); w2(4);
|
}
|
||||||
break;
|
w2(7); w2(4);
|
||||||
|
break;
|
||||||
case 3: if (count < 512) WR(0x84,1);
|
case 3:
|
||||||
|
if (count < 512)
|
||||||
|
WR(0x84, 1);
|
||||||
w3(0x40);
|
w3(0x40);
|
||||||
for (k=0;k<count;k++) w4(buf[k]);
|
for (k = 0; k < count; k++)
|
||||||
if (count < 512) WR(0x84,0);
|
w4(buf[k]);
|
||||||
break;
|
if (count < 512)
|
||||||
|
WR(0x84, 0);
|
||||||
case 4: if (count < 512) WR(0x84,1);
|
break;
|
||||||
|
case 4:
|
||||||
|
if (count < 512)
|
||||||
|
WR(0x84, 1);
|
||||||
w3(0x40);
|
w3(0x40);
|
||||||
for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
|
for (k = 0; k < count / 2; k++)
|
||||||
if (count < 512) WR(0x84,0);
|
w4w(((u16 *)buf)[k]);
|
||||||
break;
|
if (count < 512)
|
||||||
|
WR(0x84, 0);
|
||||||
case 5: if (count < 512) WR(0x84,1);
|
break;
|
||||||
|
case 5:
|
||||||
|
if (count < 512)
|
||||||
|
WR(0x84, 1);
|
||||||
w3(0x40);
|
w3(0x40);
|
||||||
for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
|
for (k = 0; k < count / 4; k++)
|
||||||
if (count < 512) WR(0x84,0);
|
w4l(((u32 *)buf)[k]);
|
||||||
break;
|
if (count < 512)
|
||||||
|
WR(0x84, 0);
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int epia_test_proto(struct pi_adapter *pi)
|
static int epia_test_proto(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ int j, k, f;
|
int j, k, f;
|
||||||
int e[2] = {0,0};
|
int e[2] = { 0, 0 };
|
||||||
char scratch[512];
|
char scratch[512];
|
||||||
|
|
||||||
epia_connect(pi);
|
epia_connect(pi);
|
||||||
for (j=0;j<2;j++) {
|
for (j = 0; j < 2; j++) {
|
||||||
WR(6,0xa0+j*0x10);
|
WR(6, 0xa0 + j * 0x10);
|
||||||
for (k=0;k<256;k++) {
|
for (k = 0; k < 256; k++) {
|
||||||
WR(2,k^0xaa);
|
WR(2, k ^ 0xaa);
|
||||||
WR(3,k^0x55);
|
WR(3, k ^ 0x55);
|
||||||
if (RR(2) != (k^0xaa)) e[j]++;
|
if (RR(2) != (k ^ 0xaa))
|
||||||
}
|
e[j]++;
|
||||||
WR(2,1); WR(3,1);
|
}
|
||||||
}
|
WR(2, 1); WR(3, 1);
|
||||||
epia_disconnect(pi);
|
}
|
||||||
|
epia_disconnect(pi);
|
||||||
|
|
||||||
f = 0;
|
f = 0;
|
||||||
epia_connect(pi);
|
epia_connect(pi);
|
||||||
WR(0x84,8);
|
WR(0x84, 8);
|
||||||
epia_read_block(pi,scratch,512);
|
epia_read_block(pi, scratch, 512);
|
||||||
for (k=0;k<256;k++) {
|
for (k = 0; k < 256; k++) {
|
||||||
if ((scratch[2*k] & 0xff) != ((k+1) & 0xff)) f++;
|
if ((scratch[2 * k] & 0xff) != ((k + 1) & 0xff))
|
||||||
if ((scratch[2*k+1] & 0xff) != ((-2-k) & 0xff)) f++;
|
f++;
|
||||||
}
|
if ((scratch[2 * k + 1] & 0xff) != ((-2 - k) & 0xff))
|
||||||
WR(0x84,0);
|
f++;
|
||||||
epia_disconnect(pi);
|
}
|
||||||
|
WR(0x84, 0);
|
||||||
|
epia_disconnect(pi);
|
||||||
|
|
||||||
dev_dbg(&pi->dev, "epia: port 0x%x, mode %d, test=(%d,%d,%d)\n",
|
dev_dbg(&pi->dev, "epia: port 0x%x, mode %d, test=(%d,%d,%d)\n",
|
||||||
pi->port, pi->mode, e[0], e[1], f);
|
pi->port, pi->mode, e[0], e[1], f);
|
||||||
|
|
||||||
return (e[0] && e[1]) || f;
|
|
||||||
|
|
||||||
|
return (e[0] && e[1]) || f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void epia_log_adapter(struct pi_adapter *pi)
|
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",
|
dev_info(&pi->dev,
|
||||||
"EPP-8","EPP-16","EPP-32"};
|
"Shuttle EPIA at 0x%x, mode %d (%s), delay %d\n",
|
||||||
|
pi->port, pi->mode, mode[pi->mode], pi->delay);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pi_protocol epia = {
|
static struct pi_protocol epia = {
|
||||||
|
@ -1,17 +1,16 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
fit2.c (c) 1998 Grant R. Guenther <grant@torque.net>
|
/*
|
||||||
Under the terms of the GNU General Public License.
|
* (c) 1998 Grant R. Guenther <grant@torque.net>
|
||||||
|
*
|
||||||
fit2.c is a low-level protocol driver for the older version
|
* fit2.c is a low-level protocol driver for the older version
|
||||||
of the Fidelity International Technology parallel port adapter.
|
* of the Fidelity International Technology parallel port adapter.
|
||||||
This adapter is used in their TransDisk 2000 and older TransDisk
|
* This adapter is used in their TransDisk 2000 and older TransDisk
|
||||||
3000 portable hard-drives. As far as I can tell, this device
|
* 3000 portable hard-drives. As far as I can tell, this device
|
||||||
supports 4-bit mode _only_.
|
* supports 4-bit mode _only_.
|
||||||
|
*
|
||||||
Newer models of the FIT products use an enhanced protocol.
|
* Newer models of the FIT products use an enhanced protocol.
|
||||||
The "fit3" protocol module should support current drives.
|
* The "fit3" protocol module should support current drives.
|
||||||
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -22,99 +21,97 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "pata_parport.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
|
* 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
|
* NB: The FIT adapter does not appear to use the control registers.
|
||||||
control register - this means that IDE reset will not work on these
|
* So, we map ALT_STATUS to STATUS and NO-OP writes to the device
|
||||||
devices.
|
* 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)
|
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);
|
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)
|
static int fit2_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||||
|
{
|
||||||
{ int a, b, r;
|
int a, b, r;
|
||||||
|
|
||||||
if (cont) {
|
if (cont) {
|
||||||
if (regr != 6) return 0xff;
|
if (regr != 6)
|
||||||
r = 7;
|
return 0xff;
|
||||||
} else r = regr + 0x10;
|
r = 7;
|
||||||
|
} else {
|
||||||
|
r = regr + 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
w2(0xc); w0(r); w2(4); w2(5);
|
w2(0xc); w0(r); w2(4); w2(5);
|
||||||
w0(0); a = r1();
|
w0(0); a = r1();
|
||||||
w0(1); b = r1();
|
w0(1); b = r1();
|
||||||
w2(4);
|
w2(4);
|
||||||
|
|
||||||
return j44(a,b);
|
return j44(a, b);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fit2_read_block(struct pi_adapter *pi, char *buf, int count)
|
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);
|
w2(0xc); w0(0x10);
|
||||||
|
|
||||||
for (k=0;k<count/4;k++) {
|
for (k = 0; k < count / 4; k++) {
|
||||||
|
|
||||||
w2(4); w2(5);
|
w2(4); w2(5);
|
||||||
w0(0); a = r1(); w0(1); b = r1();
|
w0(0); a = r1(); w0(1); b = r1();
|
||||||
w0(3); c = r1(); w0(2); d = r1();
|
w0(3); c = r1(); w0(2); d = r1();
|
||||||
buf[4*k+0] = j44(a,b);
|
buf[4 * k + 0] = j44(a, b);
|
||||||
buf[4*k+1] = j44(d,c);
|
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); 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);
|
w2(4);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fit2_write_block(struct pi_adapter *pi, char *buf, int count)
|
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(0xc); w0(0);
|
w2(5); w0(buf[2 * k + 1]);
|
||||||
for (k=0;k<count/2;k++) {
|
|
||||||
w2(4); w0(buf[2*k]);
|
|
||||||
w2(5); w0(buf[2*k+1]);
|
|
||||||
}
|
}
|
||||||
w2(4);
|
w2(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fit2_connect(struct pi_adapter *pi)
|
static void fit2_connect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ pi->saved_r0 = r0();
|
pi->saved_r0 = r0();
|
||||||
pi->saved_r2 = r2();
|
pi->saved_r2 = r2();
|
||||||
w2(0xcc);
|
w2(0xcc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fit2_disconnect(struct pi_adapter *pi)
|
static void fit2_disconnect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ w0(pi->saved_r0);
|
w0(pi->saved_r0);
|
||||||
w2(pi->saved_r2);
|
w2(pi->saved_r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fit2_log_adapter(struct pi_adapter *pi)
|
static void fit2_log_adapter(struct pi_adapter *pi)
|
||||||
|
|
||||||
{
|
{
|
||||||
dev_info(&pi->dev, "FIT 2000 adapter at 0x%x, delay %d\n",
|
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 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
fit3.c (c) 1998 Grant R. Guenther <grant@torque.net>
|
/*
|
||||||
Under the terms of the GNU General Public License.
|
* (c) 1998 Grant R. Guenther <grant@torque.net>
|
||||||
|
*
|
||||||
fit3.c is a low-level protocol driver for newer models
|
* fit3.c is a low-level protocol driver for newer models
|
||||||
of the Fidelity International Technology parallel port adapter.
|
* of the Fidelity International Technology parallel port adapter.
|
||||||
This adapter is used in their TransDisk 3000 portable
|
* This adapter is used in their TransDisk 3000 portable
|
||||||
hard-drives, as well as CD-ROM, PD-CD and other devices.
|
* hard-drives, as well as CD-ROM, PD-CD and other devices.
|
||||||
|
*
|
||||||
The TD-2000 and certain older devices use a different protocol.
|
* The TD-2000 and certain older devices use a different protocol.
|
||||||
Try the fit2 protocol module with them.
|
* Try the fit2 protocol module with them.
|
||||||
|
*
|
||||||
NB: The FIT adapters do not appear to support the control
|
* NB: The FIT adapters do not appear to support the control
|
||||||
registers. So, we map ALT_STATUS to STATUS and NO-OP writes
|
* registers. So, we map ALT_STATUS to STATUS and NO-OP writes
|
||||||
to the device control register - this means that IDE reset
|
* to the device control register - this means that IDE reset
|
||||||
will not work on these devices.
|
* will not work on these devices.
|
||||||
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -26,152 +25,155 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "pata_parport.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 w7(byte) out_p(7, byte)
|
||||||
#define r7() (in_p(7) & 0xff)
|
#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)
|
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) {
|
switch (pi->mode) {
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
case 1: w2(0xc); w0(regr); w2(0x8); w2(0xc);
|
case 1:
|
||||||
w0(val); w2(0xd);
|
w2(0xc); w0(regr); w2(0x8); w2(0xc);
|
||||||
|
w0(val); w2(0xd);
|
||||||
w0(0); w2(0xc);
|
w0(0); w2(0xc);
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
case 2: w2(0xc); w0(regr); w2(0x8); w2(0xc);
|
w2(0xc); w0(regr); w2(0x8); w2(0xc);
|
||||||
w4(val); w4(0);
|
w4(val); w4(0);
|
||||||
w2(0xc);
|
w2(0xc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fit3_read_regr(struct pi_adapter *pi, int cont, int regr)
|
static int fit3_read_regr(struct pi_adapter *pi, int cont, int regr)
|
||||||
|
{
|
||||||
{ int a, b;
|
int a, b;
|
||||||
|
|
||||||
if (cont) {
|
if (cont) {
|
||||||
if (regr != 6) return 0xff;
|
if (regr != 6)
|
||||||
regr = 7;
|
return 0xff;
|
||||||
}
|
regr = 7;
|
||||||
|
}
|
||||||
|
|
||||||
switch (pi->mode) {
|
switch (pi->mode) {
|
||||||
|
case 0:
|
||||||
case 0: w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc);
|
w2(0xc); w0(regr + 0x10); w2(0x8); w2(0xc);
|
||||||
w2(0xd); a = r1();
|
w2(0xd); a = r1();
|
||||||
w2(0xf); b = r1();
|
w2(0xf); b = r1();
|
||||||
w2(0xc);
|
w2(0xc);
|
||||||
return j44(a,b);
|
return j44(a, b);
|
||||||
|
case 1:
|
||||||
case 1: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
|
w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
|
||||||
w2(0xec); w2(0xee); w2(0xef); a = r0();
|
w2(0xec); w2(0xee); w2(0xef); a = r0();
|
||||||
w2(0xc);
|
w2(0xc);
|
||||||
return a;
|
return a;
|
||||||
|
case 2:
|
||||||
case 2: w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
|
w2(0xc); w0(regr + 0x90); w2(0x8); w2(0xc);
|
||||||
w2(0xec);
|
w2(0xec);
|
||||||
a = r4(); b = r4();
|
a = r4(); b = r4();
|
||||||
w2(0xc);
|
w2(0xc);
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
}
|
}
|
||||||
return -1;
|
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fit3_read_block(struct pi_adapter *pi, char *buf, int count)
|
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) {
|
switch (pi->mode) {
|
||||||
|
case 0:
|
||||||
case 0: w2(0xc); w0(0x10); w2(0x8); w2(0xc);
|
w2(0xc); w0(0x10); w2(0x8); w2(0xc);
|
||||||
for (k=0;k<count/2;k++) {
|
for (k = 0; k < count / 2; k++) {
|
||||||
w2(0xd); a = r1();
|
w2(0xd); a = r1();
|
||||||
w2(0xf); b = r1();
|
w2(0xf); b = r1();
|
||||||
w2(0xc); c = r1();
|
w2(0xc); c = r1();
|
||||||
w2(0xe); d = r1();
|
w2(0xe); d = r1();
|
||||||
buf[2*k ] = j44(a,b);
|
buf[2 * k] = j44(a, b);
|
||||||
buf[2*k+1] = j44(c,d);
|
buf[2 * k + 1] = j44(c, d);
|
||||||
}
|
}
|
||||||
w2(0xc);
|
w2(0xc);
|
||||||
break;
|
break;
|
||||||
|
case 1:
|
||||||
case 1: w2(0xc); w0(0x90); w2(0x8); w2(0xc);
|
w2(0xc); w0(0x90); w2(0x8); w2(0xc);
|
||||||
w2(0xec); w2(0xee);
|
w2(0xec); w2(0xee);
|
||||||
for (k=0;k<count/2;k++) {
|
for (k = 0; k < count / 2; k++) {
|
||||||
w2(0xef); a = r0();
|
w2(0xef); a = r0();
|
||||||
w2(0xee); b = r0();
|
w2(0xee); b = r0();
|
||||||
buf[2*k ] = a;
|
buf[2 * k] = a;
|
||||||
buf[2*k+1] = b;
|
buf[2 * k + 1] = b;
|
||||||
}
|
}
|
||||||
w2(0xec);
|
w2(0xec);
|
||||||
w2(0xc);
|
w2(0xc);
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
case 2: w2(0xc); w0(0x90); w2(0x8); w2(0xc);
|
w2(0xc); w0(0x90); w2(0x8); w2(0xc);
|
||||||
w2(0xec);
|
w2(0xec);
|
||||||
for (k=0;k<count;k++) buf[k] = r4();
|
for (k = 0; k < count; k++)
|
||||||
w2(0xc);
|
buf[k] = r4();
|
||||||
|
w2(0xc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fit3_write_block(struct pi_adapter *pi, char *buf, int count)
|
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 0:
|
||||||
case 1: w2(0xc); w0(0); w2(0x8); w2(0xc);
|
case 1:
|
||||||
for (k=0;k<count/2;k++) {
|
w2(0xc); w0(0); w2(0x8); w2(0xc);
|
||||||
w0(buf[2*k ]); w2(0xd);
|
for (k = 0; k < count / 2; k++) {
|
||||||
w0(buf[2*k+1]); w2(0xc);
|
w0(buf[2 * k]); w2(0xd);
|
||||||
|
w0(buf[2 * k + 1]); w2(0xc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
case 2: w2(0xc); w0(0); w2(0x8); w2(0xc);
|
w2(0xc); w0(0); w2(0x8); w2(0xc);
|
||||||
for (k=0;k<count;k++) w4(buf[k]);
|
for (k = 0; k < count; k++)
|
||||||
w2(0xc);
|
w4(buf[k]);
|
||||||
|
w2(0xc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fit3_connect(struct pi_adapter *pi)
|
static void fit3_connect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ pi->saved_r0 = r0();
|
pi->saved_r0 = r0();
|
||||||
pi->saved_r2 = r2();
|
pi->saved_r2 = r2();
|
||||||
w2(0xc); w0(0); w2(0xa);
|
w2(0xc); w0(0); w2(0xa);
|
||||||
if (pi->mode == 2) {
|
if (pi->mode == 2) {
|
||||||
w2(0xc); w0(0x9); w2(0x8); w2(0xc);
|
w2(0xc); w0(0x9);
|
||||||
}
|
w2(0x8); w2(0xc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fit3_disconnect(struct pi_adapter *pi)
|
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);
|
w0(pi->saved_r0);
|
||||||
w2(pi->saved_r2);
|
w2(pi->saved_r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fit3_log_adapter(struct pi_adapter *pi)
|
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",
|
||||||
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);
|
||||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pi_protocol fit3 = {
|
static struct pi_protocol fit3 = {
|
||||||
|
@ -1,24 +1,23 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
friq.c (c) 1998 Grant R. Guenther <grant@torque.net>
|
/*
|
||||||
Under the terms of the GNU General Public License
|
* (c) 1998 Grant R. Guenther <grant@torque.net>
|
||||||
|
*
|
||||||
friq.c is a low-level protocol driver for the Freecom "IQ"
|
* friq.c is a low-level protocol driver for the Freecom "IQ"
|
||||||
parallel port IDE adapter. Early versions of this adapter
|
* parallel port IDE adapter. Early versions of this adapter
|
||||||
use the 'frpw' protocol.
|
* use the 'frpw' protocol.
|
||||||
|
*
|
||||||
Freecom uses this adapter in a battery powered external
|
* Freecom uses this adapter in a battery powered external
|
||||||
CD-ROM drive. It is also used in LS-120 drives by
|
* CD-ROM drive. It is also used in LS-120 drives by
|
||||||
Maxell and Panasonic, and other devices.
|
* Maxell and Panasonic, and other devices.
|
||||||
|
*
|
||||||
The battery powered drive requires software support to
|
* The battery powered drive requires software support to
|
||||||
control the power to the drive. This module enables the
|
* control the power to the drive. This module enables the
|
||||||
drive power when the high level driver (pcd) is loaded
|
* drive power when the high level driver (pcd) is loaded
|
||||||
and disables it when the module is unloaded. Note, if
|
* and disables it when the module is unloaded. Note, if
|
||||||
the friq module is built in to the kernel, the power
|
* the friq module is built in to the kernel, the power
|
||||||
will never be switched off, so other means should be
|
* will never be switched off, so other means should be
|
||||||
used to conserve battery power.
|
* used to conserve battery power.
|
||||||
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -29,197 +28,206 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "pata_parport.h"
|
#include "pata_parport.h"
|
||||||
|
|
||||||
#define CMD(x) w2(4);w0(0xff);w0(0xff);w0(0x73);w0(0x73);\
|
#define CMD(x) \
|
||||||
w0(0xc9);w0(0xc9);w0(0x26);w0(0x26);w0(x);w0(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
|
* cont = 0 - access the IDE register file
|
||||||
*/
|
* cont = 1 - access the IDE command set
|
||||||
|
*/
|
||||||
static int cont_map[2] = { 0x08, 0x10 };
|
static int cont_map[2] = { 0x08, 0x10 };
|
||||||
|
|
||||||
static int friq_read_regr(struct pi_adapter *pi, int cont, int regr)
|
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];
|
r = regr + cont_map[cont];
|
||||||
|
|
||||||
CMD(r);
|
CMD(r);
|
||||||
w2(6); l = r1();
|
w2(6); l = r1();
|
||||||
w2(4); h = r1();
|
w2(4); h = r1();
|
||||||
w2(4);
|
w2(4);
|
||||||
|
|
||||||
return j44(l,h);
|
|
||||||
|
|
||||||
|
return j44(l, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void friq_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
static void friq_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||||
|
{
|
||||||
{ int r;
|
int r = regr + cont_map[cont];
|
||||||
|
|
||||||
r = regr + cont_map[cont];
|
|
||||||
|
|
||||||
CMD(r);
|
CMD(r);
|
||||||
w0(val);
|
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)
|
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) {
|
||||||
|
|
||||||
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) {
|
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
case 1: CMD(8); w2(5);
|
CMD(regr);
|
||||||
for (k=0;k<count;k++) {
|
for (k = 0; k < count; k++) {
|
||||||
w0(buf[k]);
|
w2(6); l = r1();
|
||||||
w2(7);w2(5);
|
w2(4); h = r1();
|
||||||
|
buf[k] = j44(l, h);
|
||||||
}
|
}
|
||||||
w2(4);
|
w2(4);
|
||||||
break;
|
break;
|
||||||
|
case 1:
|
||||||
case 2: CMD(0xc8); w2(5);
|
ph = 2;
|
||||||
for (k=0;k<count;k++) w4(buf[k]);
|
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);
|
w2(4);
|
||||||
break;
|
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();
|
static void friq_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||||
pi->saved_r2 = r2();
|
{
|
||||||
|
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);
|
w2(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void friq_disconnect(struct pi_adapter *pi)
|
static void friq_disconnect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ CMD(0x20);
|
CMD(0x20);
|
||||||
w0(pi->saved_r0);
|
w0(pi->saved_r0);
|
||||||
w2(pi->saved_r2);
|
w2(pi->saved_r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int friq_test_proto(struct pi_adapter *pi)
|
static int friq_test_proto(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ int j, k, r;
|
int j, k, r;
|
||||||
int e[2] = {0,0};
|
int e[2] = { 0, 0 };
|
||||||
char scratch[512];
|
char scratch[512];
|
||||||
|
|
||||||
pi->saved_r0 = r0();
|
pi->saved_r0 = r0();
|
||||||
w0(0xff); udelay(20); CMD(0x3d); /* turn the power on */
|
w0(0xff); udelay(20); CMD(0x3d); /* turn the power on */
|
||||||
udelay(500);
|
udelay(500);
|
||||||
w0(pi->saved_r0);
|
w0(pi->saved_r0);
|
||||||
|
|
||||||
friq_connect(pi);
|
friq_connect(pi);
|
||||||
for (j=0;j<2;j++) {
|
for (j = 0; j < 2; j++) {
|
||||||
friq_write_regr(pi,0,6,0xa0+j*0x10);
|
friq_write_regr(pi, 0, 6, 0xa0 + j * 0x10);
|
||||||
for (k=0;k<256;k++) {
|
for (k = 0; k < 256; k++) {
|
||||||
friq_write_regr(pi,0,2,k^0xaa);
|
friq_write_regr(pi, 0, 2, k ^ 0xaa);
|
||||||
friq_write_regr(pi,0,3,k^0x55);
|
friq_write_regr(pi, 0, 3, k ^ 0x55);
|
||||||
if (friq_read_regr(pi,0,2) != (k^0xaa)) e[j]++;
|
if (friq_read_regr(pi, 0, 2) != (k ^ 0xaa))
|
||||||
}
|
e[j]++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
friq_disconnect(pi);
|
friq_disconnect(pi);
|
||||||
|
|
||||||
friq_connect(pi);
|
friq_connect(pi);
|
||||||
friq_read_block_int(pi,scratch,512,0x10);
|
friq_read_block_int(pi, scratch, 512, 0x10);
|
||||||
r = 0;
|
r = 0;
|
||||||
for (k=0;k<128;k++) if (scratch[k] != k) r++;
|
for (k = 0; k < 128; k++) {
|
||||||
|
if (scratch[k] != k)
|
||||||
|
r++;
|
||||||
|
}
|
||||||
friq_disconnect(pi);
|
friq_disconnect(pi);
|
||||||
|
|
||||||
dev_dbg(&pi->dev, "friq: port 0x%x, mode %d, test=(%d,%d,%d)\n",
|
dev_dbg(&pi->dev,
|
||||||
pi->port, pi->mode, e[0], e[1], r);
|
"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)
|
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",
|
dev_info(&pi->dev,
|
||||||
"EPP-8","EPP-16","EPP-32"};
|
"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;
|
pi->private = 1;
|
||||||
friq_connect(pi);
|
friq_connect(pi);
|
||||||
CMD(0x9e); /* disable sleep timer */
|
CMD(0x9e); /* disable sleep timer */
|
||||||
friq_disconnect(pi);
|
friq_disconnect(pi);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void friq_release_proto(struct pi_adapter *pi)
|
static void friq_release_proto(struct pi_adapter *pi)
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
frpw.c (c) 1996-8 Grant R. Guenther <grant@torque.net>
|
/*
|
||||||
Under the terms of the GNU General Public License
|
* (c) 1996-1998 Grant R. Guenther <grant@torque.net>
|
||||||
|
*
|
||||||
frpw.c is a low-level protocol driver for the Freecom "Power"
|
* frpw.c is a low-level protocol driver for the Freecom "Power" parallel port
|
||||||
parallel port IDE adapter.
|
* IDE adapter.
|
||||||
|
*
|
||||||
Some applications of this adapter may require a "printer" reset
|
* Some applications of this adapter may require a "printer" reset prior to
|
||||||
prior to loading the driver. This can be done by loading and
|
* loading the driver. This can be done by loading and unloading the "lp"
|
||||||
unloading the "lp" driver, or it can be done by this driver
|
* driver, or it can be done by this driver if you define FRPW_HARD_RESET.
|
||||||
if you define FRPW_HARD_RESET. The latter is not recommended
|
* The latter is not recommended as it may upset devices on other ports.
|
||||||
as it may upset devices on other ports.
|
*/
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.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 cec4 w2(0xc);w2(0xe);w2(0xe);w2(0xc);w2(4);w2(4);w2(4);
|
||||||
#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
|
* cont = 0 - access the IDE register file
|
||||||
*/
|
* cont = 1 - access the IDE command set
|
||||||
|
*/
|
||||||
static int cont_map[2] = { 0x08, 0x10 };
|
static int cont_map[2] = { 0x08, 0x10 };
|
||||||
|
|
||||||
static int frpw_read_regr(struct pi_adapter *pi, int cont, int regr)
|
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];
|
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;
|
w0(r); cec4;
|
||||||
w2(6); l = r1();
|
w2(6); l = r1();
|
||||||
w2(4); h = r1();
|
w2(4); h = r1();
|
||||||
w2(4);
|
w2(4);
|
||||||
|
|
||||||
return j44(l,h);
|
|
||||||
|
|
||||||
|
return j44(l, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void frpw_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
static void frpw_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||||
|
{
|
||||||
|
int r = regr + cont_map[cont];
|
||||||
|
|
||||||
{ int r;
|
w2(4); w0(r); cec4;
|
||||||
|
|
||||||
r = regr + cont_map[cont];
|
|
||||||
|
|
||||||
w2(4); w0(r); cec4;
|
|
||||||
w0(val);
|
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)
|
static void frpw_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: 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) {
|
|
||||||
|
|
||||||
|
switch (pi->mode) {
|
||||||
case 0:
|
case 0:
|
||||||
case 1:
|
w2(4); w0(regr); cec4;
|
||||||
case 2: w2(4); w0(8); cec4; w2(5);
|
for (k = 0; k < count; k++) {
|
||||||
for (k=0;k<count;k++) {
|
w2(6); l = r1();
|
||||||
w0(buf[k]);
|
w2(4); h = r1();
|
||||||
w2(7);w2(5);
|
buf[k] = j44(l, h);
|
||||||
}
|
}
|
||||||
w2(4);
|
w2(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: w2(4); w0(0xc8); cec4; w2(5);
|
case 1:
|
||||||
for (k=0;k<count;k++) w4(buf[k]);
|
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);
|
w2(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: w2(4); w0(0xc8); cec4; w2(5);
|
case 3:
|
||||||
for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
|
w2(4); w0(regr + 0x80); cec4;
|
||||||
w2(4);
|
for (k = 0; k < count - 2; k++)
|
||||||
break;
|
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);
|
case 4:
|
||||||
for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
|
w2(4); w0(regr + 0x80); cec4;
|
||||||
w2(4);
|
for (k = 0; k < count / 2 - 1; k++)
|
||||||
break;
|
((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)
|
static void frpw_connect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ pi->saved_r0 = r0();
|
pi->saved_r0 = r0();
|
||||||
pi->saved_r2 = r2();
|
pi->saved_r2 = r2();
|
||||||
w2(4);
|
w2(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void frpw_disconnect(struct pi_adapter *pi)
|
static void frpw_disconnect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ w2(4); w0(0x20); cec4;
|
w2(4); w0(0x20); cec4;
|
||||||
w0(pi->saved_r0);
|
w0(pi->saved_r0);
|
||||||
w2(pi->saved_r2);
|
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
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
|
#ifdef FRPW_HARD_RESET
|
||||||
w0(0); w2(8); udelay(50); w2(0xc); /* parallel bus 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_r0 = r0();
|
||||||
pi->saved_r2 = r2();
|
pi->saved_r2 = r2();
|
||||||
|
|
||||||
w2(4); w0(4); w2(6); w2(7);
|
w2(4); w0(4); w2(6); w2(7);
|
||||||
a = r1() & 0xff; w2(4); b = r1() & 0xff;
|
a = r1() & 0xff; w2(4); b = r1() & 0xff;
|
||||||
w2(0xc); w2(0xe); w2(4);
|
w2(0xc); w2(0xe); w2(4);
|
||||||
@ -200,65 +209,70 @@ static int frpw_test_pnp(struct pi_adapter *pi)
|
|||||||
w0(pi->saved_r0);
|
w0(pi->saved_r0);
|
||||||
w2(pi->saved_r2);
|
w2(pi->saved_r2);
|
||||||
|
|
||||||
return ((~a&0x40) && (b&0x40));
|
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]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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)
|
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",
|
dev_info(&pi->dev,
|
||||||
((pi->private % 2) == 0) ? "Xilinx" : "ASIC",
|
"Freecom (%s) adapter at 0x%x, mode %d (%s), delay %d\n",
|
||||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
((pi->private & 0x1) == 0) ? "Xilinx" : "ASIC",
|
||||||
|
pi->port, pi->mode, mode[pi->mode], pi->delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pi_protocol frpw = {
|
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>
|
* (c) 1997-1998 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
|
||||||
This is a low-level driver for the KBIC-951A and KBIC-971A
|
* parallel to IDE adapter chips from KingByte Information Systems.
|
||||||
parallel to IDE adapter chips from KingByte Information Systems.
|
*
|
||||||
|
* The chips are almost identical, however, the wakeup code
|
||||||
The chips are almost identical, however, the wakeup code
|
* required for the 971A interferes with the correct operation of
|
||||||
required for the 971A interferes with the correct operation of
|
* the 951A, so this driver registers itself twice, once for
|
||||||
the 951A, so this driver registers itself twice, once for
|
* each chip.
|
||||||
each chip.
|
*/
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -21,212 +20,223 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "pata_parport.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 j44(a, b) ((((a >> 4) & 0x0f) | (b & 0xf0)) ^ 0x88)
|
||||||
#define j53(w) (((w>>3)&0x1f)|((w>>4)&0xe0))
|
#define j53(w) (((w >> 3) & 0x1f) | ((w >> 4) & 0xe0))
|
||||||
|
|
||||||
|
|
||||||
/* 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] = { 0x80, 0x40 };
|
static int cont_map[2] = { 0x80, 0x40 };
|
||||||
|
|
||||||
static int kbic_read_regr(struct pi_adapter *pi, int cont, int regr)
|
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) {
|
switch (pi->mode) {
|
||||||
|
case 0:
|
||||||
case 0: w0(regr|0x18|s); w2(4); w2(6); w2(4); w2(1); w0(8);
|
w0(regr | 0x18 | s); w2(4); w2(6); w2(4); w2(1); w0(8);
|
||||||
a = r1(); w0(0x28); b = r1(); w2(4);
|
a = r1(); w0(0x28); b = r1(); w2(4);
|
||||||
return j44(a,b);
|
return j44(a, b);
|
||||||
|
case 1:
|
||||||
case 1: w0(regr|0x38|s); w2(4); w2(6); w2(4); w2(5); w0(8);
|
w0(regr|0x38 | s); w2(4); w2(6); w2(4); w2(5); w0(8);
|
||||||
a = r12w(); w2(4);
|
a = r12w(); w2(4);
|
||||||
return j53(a);
|
return j53(a);
|
||||||
|
case 2:
|
||||||
case 2: w0(regr|0x08|s); w2(4); w2(6); w2(4); w2(0xa5); w2(0xa1);
|
w0(regr | 0x08 | s); w2(4); w2(6); w2(4); w2(0xa5); w2(0xa1);
|
||||||
a = r0(); w2(4);
|
a = r0(); w2(4);
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
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);
|
a = r4(); b = r4(); w2(4); w2(0); w2(4);
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kbic_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
static void kbic_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||||
|
{
|
||||||
|
int s = cont_map[cont];
|
||||||
|
|
||||||
{ int s;
|
switch (pi->mode) {
|
||||||
|
case 0:
|
||||||
s = cont_map[cont];
|
case 1:
|
||||||
|
case 2:
|
||||||
switch (pi->mode) {
|
w0(regr | 0x10 | s); w2(4); w2(6); w2(4);
|
||||||
|
|
||||||
case 0:
|
|
||||||
case 1:
|
|
||||||
case 2: w0(regr|0x10|s); w2(4); w2(6); w2(4);
|
|
||||||
w0(val); w2(5); w2(4);
|
w0(val); w2(5); w2(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
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);
|
w4(val); w4(val);
|
||||||
w2(4); w2(0); w2(4);
|
w2(4); w2(0); w2(4);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void k951_connect(struct pi_adapter *pi)
|
static void k951_connect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ pi->saved_r0 = r0();
|
pi->saved_r0 = r0();
|
||||||
pi->saved_r2 = r2();
|
pi->saved_r2 = r2();
|
||||||
w2(4);
|
w2(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void k951_disconnect(struct pi_adapter *pi)
|
static void k951_disconnect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ w0(pi->saved_r0);
|
w0(pi->saved_r0);
|
||||||
w2(pi->saved_r2);
|
w2(pi->saved_r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CCP(x) w2(0xc4);w0(0xaa);w0(0x55);w0(0);w0(0xff);w0(0x87);\
|
#define CCP(x) \
|
||||||
w0(0x78);w0(x);w2(0xc5);w2(0xc4);w0(0xff);
|
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)
|
static void k971_connect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ pi->saved_r0 = r0();
|
pi->saved_r0 = r0();
|
||||||
pi->saved_r2 = r2();
|
pi->saved_r2 = r2();
|
||||||
CCP(0x20);
|
CCP(0x20);
|
||||||
w2(4);
|
w2(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void k971_disconnect(struct pi_adapter *pi)
|
static void k971_disconnect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ CCP(0x30);
|
CCP(0x30);
|
||||||
w0(pi->saved_r0);
|
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)
|
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:
|
||||||
switch (pi->mode) {
|
w0(0x98); w2(4); w2(6); w2(4);
|
||||||
|
for (k = 0; k < count / 2; k++) {
|
||||||
case 0: w0(0x98); w2(4); w2(6); w2(4);
|
w2(1); w0(8);
|
||||||
for (k=0;k<count/2;k++) {
|
a = r1();
|
||||||
w2(1); w0(8); a = r1();
|
w0(0x28);
|
||||||
w0(0x28); b = r1();
|
b = r1();
|
||||||
buf[2*k] = j44(a,b);
|
buf[2 * k] = j44(a, b);
|
||||||
w2(5); b = r1();
|
w2(5);
|
||||||
w0(8); a = r1();
|
b = r1();
|
||||||
buf[2*k+1] = j44(a,b);
|
w0(8);
|
||||||
|
a = r1();
|
||||||
|
buf[2 * k + 1] = j44(a, b);
|
||||||
w2(4);
|
w2(4);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 1:
|
||||||
case 1: w0(0xb8); w2(4); w2(6); w2(4);
|
w0(0xb8); w2(4); w2(6); w2(4);
|
||||||
for (k=0;k<count/4;k++) {
|
for (k = 0; k < count / 4; k++) {
|
||||||
w0(0xb8);
|
w0(0xb8);
|
||||||
w2(4); w2(5);
|
|
||||||
w0(8); buf[4*k] = j53(r12w());
|
|
||||||
w0(0xb8); buf[4*k+1] = j53(r12w());
|
|
||||||
w2(4); w2(5);
|
w2(4); w2(5);
|
||||||
buf[4*k+3] = j53(r12w());
|
w0(8);
|
||||||
w0(8); buf[4*k+2] = j53(r12w());
|
buf[4 * k] = j53(r12w());
|
||||||
}
|
w0(0xb8);
|
||||||
w2(4);
|
buf[4 * k + 1] = j53(r12w());
|
||||||
break;
|
w2(4); w2(5);
|
||||||
|
buf[4 * k + 3] = j53(r12w());
|
||||||
case 2: w0(0x88); w2(4); w2(6); w2(4);
|
w0(8);
|
||||||
for (k=0;k<count/2;k++) {
|
buf[4 * k + 2] = j53(r12w());
|
||||||
w2(0xa0); w2(0xa1); buf[2*k] = r0();
|
}
|
||||||
w2(0xa5); buf[2*k+1] = r0();
|
w2(4);
|
||||||
}
|
break;
|
||||||
w2(4);
|
case 2:
|
||||||
break;
|
w0(0x88); w2(4); w2(6); w2(4);
|
||||||
|
for (k = 0; k < count / 2; k++) {
|
||||||
case 3: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
w2(0xa0); w2(0xa1);
|
||||||
for (k=0;k<count;k++) buf[k] = r4();
|
buf[2 * k] = r0();
|
||||||
w2(4); w2(0); w2(4);
|
w2(0xa5);
|
||||||
break;
|
buf[2 * k + 1] = r0();
|
||||||
|
}
|
||||||
case 4: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
w2(4);
|
||||||
for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
|
break;
|
||||||
w2(4); w2(0); w2(4);
|
case 3:
|
||||||
break;
|
w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||||
|
for (k = 0; k < count; k++)
|
||||||
case 5: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
buf[k] = r4();
|
||||||
for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
|
w2(4); w2(0); w2(4);
|
||||||
w2(4); w2(0); w2(4);
|
break;
|
||||||
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)
|
static void kbic_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
{ int k;
|
switch (pi->mode) {
|
||||||
|
case 0:
|
||||||
switch (pi->mode) {
|
case 1:
|
||||||
|
case 2:
|
||||||
case 0:
|
w0(0x90); w2(4); w2(6); w2(4);
|
||||||
case 1:
|
for (k = 0; k < count / 2; k++) {
|
||||||
case 2: w0(0x90); w2(4); w2(6); w2(4);
|
w0(buf[2 * k + 1]);
|
||||||
for(k=0;k<count/2;k++) {
|
w2(0); w2(4);
|
||||||
w0(buf[2*k+1]); w2(0); w2(4);
|
w0(buf[2 * k]);
|
||||||
w0(buf[2*k]); w2(5); w2(4);
|
w2(5); w2(4);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
case 3: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||||
for(k=0;k<count/2;k++) {
|
for (k = 0; k < count / 2; k++) {
|
||||||
w4(buf[2*k+1]);
|
w4(buf[2 * k + 1]);
|
||||||
w4(buf[2*k]);
|
w4(buf[2 * k]);
|
||||||
}
|
}
|
||||||
w2(4); w2(0); w2(4);
|
w2(4); w2(0); w2(4);
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
case 4: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||||
for (k = 0; k < count / 2; k++)
|
for (k = 0; k < count / 2; k++)
|
||||||
w4w(swab16(((u16 *)buf)[k]));
|
w4w(swab16(((u16 *)buf)[k]));
|
||||||
w2(4); w2(0); w2(4);
|
w2(4); w2(0); w2(4);
|
||||||
break;
|
break;
|
||||||
|
case 5:
|
||||||
case 5: w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
w0(0xa0); w2(4); w2(6); w2(4); w3(0);
|
||||||
for (k = 0; k < count / 4; k++)
|
for (k = 0; k < count / 4; k++)
|
||||||
w4l(swab16(((u16 *)buf)[2 * k]) |
|
w4l(swab16(((u16 *)buf)[2 * k]) |
|
||||||
swab16(((u16 *)buf)[2 * k + 1]) << 16);
|
swab16(((u16 *)buf)[2 * k + 1]) << 16);
|
||||||
w2(4); w2(0); w2(4);
|
w2(4); w2(0); w2(4);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void kbic_log_adapter(struct pi_adapter *pi, char *chip)
|
static void kbic_log_adapter(struct pi_adapter *pi, char *chip)
|
||||||
|
{
|
||||||
{ char *mode_string[6] = {"4-bit","5/3","8-bit",
|
char *mode[6] = { "4-bit", "5/3", "8-bit", "EPP-8", "EPP_16", "EPP-32"};
|
||||||
"EPP-8","EPP_16","EPP-32"};
|
|
||||||
|
|
||||||
dev_info(&pi->dev, "KingByte %s at 0x%x, mode %d (%s), delay %d\n",
|
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)
|
static void k951_log_adapter(struct pi_adapter *pi)
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
ktti.c (c) 1998 Grant R. Guenther <grant@torque.net>
|
/*
|
||||||
Under the terms of the GNU General Public License.
|
* (c) 1998 Grant R. Guenther <grant@torque.net>
|
||||||
|
*
|
||||||
ktti.c is a low-level protocol driver for the KT Technology
|
* ktti.c is a low-level protocol driver for the KT Technology
|
||||||
parallel port adapter. This adapter is used in the "PHd"
|
* parallel port adapter. This adapter is used in the "PHd"
|
||||||
portable hard-drives. As far as I can tell, this device
|
* portable hard-drives. As far as I can tell, this device
|
||||||
supports 4-bit mode _only_.
|
* supports 4-bit mode _only_.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
@ -18,80 +17,76 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "pata_parport.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
|
* cont = 0 - access the IDE register file
|
||||||
*/
|
* cont = 1 - access the IDE command set
|
||||||
|
*/
|
||||||
static int cont_map[2] = { 0x10, 0x08 };
|
static int cont_map[2] = { 0x10, 0x08 };
|
||||||
|
|
||||||
static void ktti_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
static void ktti_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||||
|
{
|
||||||
|
int r = regr + cont_map[cont];
|
||||||
|
|
||||||
{ int r;
|
w0(r); w2(0xb); w2(0xa); w2(3); w2(6);
|
||||||
|
|
||||||
r = regr + cont_map[cont];
|
|
||||||
|
|
||||||
w0(r); w2(0xb); w2(0xa); w2(3); w2(6);
|
|
||||||
w0(val); w2(3); w0(0); w2(6); w2(0xb);
|
w0(val); w2(3); w0(0); w2(6); w2(0xb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ktti_read_regr(struct pi_adapter *pi, int cont, int regr)
|
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];
|
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);
|
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)
|
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);
|
w0(0x10); w2(0xb); w2(0xa); w2(9); w2(0xc); w2(9);
|
||||||
a = r1(); w2(0xc); b = r1(); 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);
|
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)
|
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(0x10); w2(0xb); w2(0xa); w2(3); w2(6);
|
||||||
w0(buf[2*k]); w2(3);
|
w0(buf[2 * k]); w2(3);
|
||||||
w0(buf[2*k+1]); w2(6);
|
w0(buf[2 * k + 1]); w2(6);
|
||||||
w2(0xb);
|
w2(0xb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ktti_connect(struct pi_adapter *pi)
|
static void ktti_connect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ pi->saved_r0 = r0();
|
pi->saved_r0 = r0();
|
||||||
pi->saved_r2 = r2();
|
pi->saved_r2 = r2();
|
||||||
w2(0xb); w2(0xa); w0(0); w2(3); w2(6);
|
w2(0xb); w2(0xa); w0(0); w2(3); w2(6);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ktti_disconnect(struct pi_adapter *pi)
|
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);
|
w0(pi->saved_r0);
|
||||||
w2(pi->saved_r2);
|
w2(pi->saved_r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ktti_log_adapter(struct pi_adapter *pi)
|
static void ktti_log_adapter(struct pi_adapter *pi)
|
||||||
|
|
||||||
{
|
{
|
||||||
dev_info(&pi->dev, "KT adapter at 0x%x, delay %d\n",
|
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 = {
|
static struct pi_protocol ktti = {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
on20.c (c) 1996-8 Grant R. Guenther <grant@torque.net>
|
/*
|
||||||
Under the terms of the GNU General Public License.
|
* (c) 1996-1998 Grant R. Guenther <grant@torque.net>
|
||||||
|
*
|
||||||
on20.c is a low-level protocol driver for the
|
* on20.c is a low-level protocol driver for the
|
||||||
Onspec 90c20 parallel to IDE adapter.
|
* Onspec 90c20 parallel to IDE adapter.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -15,99 +15,114 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "pata_parport.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 op(f) \
|
||||||
#define vl(v) w2(4);w0(v);w2(5);w2(7);w2(5);w2(4);
|
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
|
#define j44(a, b) (((a >> 4) & 0x0f) | (b & 0xf0))
|
||||||
cont = 1 - access the IDE command set
|
|
||||||
*/
|
/*
|
||||||
|
* 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)
|
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);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on20_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
static void on20_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||||
|
{
|
||||||
|
int r = (regr << 2) + 1 + cont;
|
||||||
|
|
||||||
{ int r;
|
op(1); vl(r);
|
||||||
|
op(0); vl(val);
|
||||||
r = (regr<<2) + 1 + cont;
|
|
||||||
|
|
||||||
op(1); vl(r);
|
|
||||||
op(0); vl(val);
|
|
||||||
op(0); vl(val);
|
op(0); vl(val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on20_connect(struct pi_adapter *pi)
|
static void on20_connect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
|
pi->saved_r0 = r0();
|
||||||
|
pi->saved_r2 = r2();
|
||||||
|
|
||||||
{ pi->saved_r0 = r0();
|
w2(4); w0(0); w2(0xc); w2(4); w2(6); w2(4); w2(6); w2(4);
|
||||||
pi->saved_r2 = r2();
|
if (pi->mode) {
|
||||||
|
op(2); vl(8); op(2); vl(9);
|
||||||
w2(4);w0(0);w2(0xc);w2(4);w2(6);w2(4);w2(6);w2(4);
|
} else {
|
||||||
if (pi->mode) { op(2); vl(8); op(2); vl(9); }
|
op(2); vl(0); op(2); vl(8);
|
||||||
else { op(2); vl(0); op(2); vl(8); }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on20_disconnect(struct pi_adapter *pi)
|
static void on20_disconnect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ w2(4);w0(7);w2(4);w2(0xc);w2(4);
|
w2(4); w0(7); w2(4); w2(0xc); w2(4);
|
||||||
w0(pi->saved_r0);
|
w0(pi->saved_r0);
|
||||||
w2(pi->saved_r2);
|
w2(pi->saved_r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on20_read_block(struct pi_adapter *pi, char *buf, int count)
|
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);
|
op(1); vl(1); op(0);
|
||||||
|
|
||||||
for (k=0;k<count;k++)
|
for (k = 0; k < count; k++) {
|
||||||
if (pi->mode) {
|
if (pi->mode) {
|
||||||
w2(4); w2(0x26); buf[k] = r0();
|
w2(4); w2(0x26); buf[k] = r0();
|
||||||
} else {
|
} else {
|
||||||
w2(6); l = r1(); w2(4);
|
w2(6); l = r1(); w2(4);
|
||||||
w2(6); h = r1(); w2(4);
|
w2(6); h = r1(); w2(4);
|
||||||
buf[k] = j44(l,h);
|
buf[k] = j44(l, h);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
w2(4);
|
w2(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on20_write_block(struct pi_adapter *pi, char *buf, int count)
|
static void on20_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||||
|
{
|
||||||
{ int k;
|
int k;
|
||||||
|
|
||||||
op(1); vl(1); op(0);
|
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);
|
w2(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on20_log_adapter(struct pi_adapter *pi)
|
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",
|
||||||
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);
|
||||||
pi->port, pi->mode, mode_string[pi->mode], pi->delay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pi_protocol on20 = {
|
static struct pi_protocol on20 = {
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
/*
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
on26.c (c) 1997-8 Grant R. Guenther <grant@torque.net>
|
/*
|
||||||
Under the terms of the GNU General Public License.
|
* (c) 1997-1998 Grant R. Guenther <grant@torque.net>
|
||||||
|
*
|
||||||
on26.c is a low-level protocol driver for the
|
* on26.c is a low-level protocol driver for the
|
||||||
OnSpec 90c26 parallel to IDE adapter chip.
|
* OnSpec 90c26 parallel to IDE adapter chip.
|
||||||
|
*/
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@ -16,260 +15,281 @@
|
|||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include "pata_parport.h"
|
#include "pata_parport.h"
|
||||||
|
|
||||||
/* mode codes: 0 nybble reads, 8-bit writes
|
/*
|
||||||
1 8-bit reads and writes
|
* mode codes: 0 nybble reads, 8-bit writes
|
||||||
2 8-bit EPP mode
|
* 1 8-bit reads and writes
|
||||||
3 EPP-16
|
* 2 8-bit EPP mode
|
||||||
4 EPP-32
|
* 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 P1 \
|
||||||
#define P2 w2(5);w2(7);w2(5);w2(4);
|
do { \
|
||||||
|
w2(5); w2(0xd); w2(5); w2(0xd); w2(5); w2(4); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
/* cont = 0 - access the IDE register file
|
#define P2 \
|
||||||
cont = 1 - access the IDE command set
|
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)
|
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:
|
||||||
switch (pi->mode) {
|
w0(1); P1; w0(r); P2; w0(0); P1;
|
||||||
|
|
||||||
case 0: w0(1); P1; w0(r); P2; w0(0); P1;
|
|
||||||
w2(6); a = r1(); w2(4);
|
w2(6); a = r1(); w2(4);
|
||||||
w2(6); b = r1(); w2(4);
|
w2(6); b = r1(); w2(4);
|
||||||
w2(6); w2(4); w2(6); w2(4);
|
w2(6); w2(4); w2(6); w2(4);
|
||||||
return j44(a,b);
|
return j44(a, b);
|
||||||
|
case 1:
|
||||||
case 1: w0(1); P1; w0(r); P2; w0(0); P1;
|
w0(1); P1; w0(r); P2; w0(0); P1;
|
||||||
w2(0x26); a = r0(); w2(4); w2(0x26); w2(4);
|
w2(0x26); a = r0(); w2(4); w2(0x26); w2(4);
|
||||||
return a;
|
return a;
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
case 3:
|
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);
|
w3(0); w3(0); w2(0x24); a = r4(); w2(4);
|
||||||
w2(0x24); (void)r4(); w2(4);
|
w2(0x24); (void)r4(); w2(4);
|
||||||
return a;
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
return -1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CCP(x) w0(0xfe);w0(0xaa);w0(0x55);w0(0);w0(0xff);\
|
static void on26_write_regr(struct pi_adapter *pi, int cont, int regr, int val)
|
||||||
w0(0x87);w0(0x78);w0(x);w2(4);w2(5);w2(4);w0(0xff);
|
{
|
||||||
|
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)
|
static void on26_connect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ int x;
|
int x;
|
||||||
|
|
||||||
pi->saved_r0 = r0();
|
pi->saved_r0 = r0();
|
||||||
pi->saved_r2 = r2();
|
pi->saved_r2 = r2();
|
||||||
|
|
||||||
CCP(0x20);
|
CCP(0x20);
|
||||||
x = 8; if (pi->mode) x = 9;
|
if (pi->mode)
|
||||||
|
x = 9;
|
||||||
|
else
|
||||||
|
x = 8;
|
||||||
|
|
||||||
w0(2); P1; w0(8); P2;
|
w0(2); P1; w0(8); P2;
|
||||||
w0(2); P1; w0(x); P2;
|
w0(2); P1; w0(x); P2;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on26_disconnect(struct pi_adapter *pi)
|
static void on26_disconnect(struct pi_adapter *pi)
|
||||||
|
{
|
||||||
{ if (pi->mode >= 2) { w3(4); w3(4); w3(4); w3(4); }
|
if (pi->mode >= 2) {
|
||||||
else { w0(4); P1; w0(4); P1; }
|
w3(4); w3(4); w3(4); w3(4);
|
||||||
|
} else {
|
||||||
|
w0(4); P1; w0(4); P1;
|
||||||
|
}
|
||||||
CCP(0x30);
|
CCP(0x30);
|
||||||
w0(pi->saved_r0);
|
w0(pi->saved_r0);
|
||||||
w2(pi->saved_r2);
|
w2(pi->saved_r2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define RESET_WAIT 200
|
#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();
|
d = pi->delay;
|
||||||
pi->saved_r2 = r2();
|
m = pi->mode;
|
||||||
|
pi->delay = 5;
|
||||||
|
pi->mode = 0;
|
||||||
|
|
||||||
d = pi->delay;
|
w2(0xc);
|
||||||
m = pi->mode;
|
|
||||||
pi->delay = 5;
|
|
||||||
pi->mode = 0;
|
|
||||||
|
|
||||||
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);
|
if (i == 0xb5f) {
|
||||||
i = ((r1() & 0xf0) << 4); w0(0x87);
|
w0(2); P1; w0(0); P2;
|
||||||
i |= (r1() & 0xf0); w0(0x78);
|
w0(3); P1; w0(0); P2;
|
||||||
w0(0x20);w2(4);w2(5);
|
w0(2); P1; w0(8); P2; udelay(100);
|
||||||
i |= ((r1() & 0xf0) >> 4);
|
w0(2); P1; w0(0xa); P2; udelay(100);
|
||||||
w2(4);w0(0xff);
|
w0(2); P1; w0(8); P2; udelay(1000);
|
||||||
|
|
||||||
if (i == 0xb5f) {
|
on26_write_regr(pi, 0, 6, 0xa0);
|
||||||
|
|
||||||
w0(2); P1; w0(0); P2;
|
for (i = 0; i < RESET_WAIT; i++) {
|
||||||
w0(3); P1; w0(0); P2;
|
on26_write_regr(pi, 0, 6, 0xa0);
|
||||||
w0(2); P1; w0(8); P2; udelay(100);
|
x = on26_read_regr(pi, 0, 7);
|
||||||
w0(2); P1; w0(0xa); P2; udelay(100);
|
on26_write_regr(pi, 0, 6, 0xb0);
|
||||||
w0(2); P1; w0(8); P2; udelay(1000);
|
y = on26_read_regr(pi, 0, 7);
|
||||||
|
if (!((x & 0x80) || (y & 0x80)))
|
||||||
on26_write_regr(pi,0,6,0xa0);
|
break;
|
||||||
|
mdelay(100);
|
||||||
|
}
|
||||||
|
|
||||||
for (i=0;i<RESET_WAIT;i++) {
|
if (i == RESET_WAIT)
|
||||||
on26_write_regr(pi,0,6,0xa0);
|
dev_err(&pi->dev,
|
||||||
x = on26_read_regr(pi,0,7);
|
"on26: Device reset failed (%x,%x)\n", x, y);
|
||||||
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)
|
w0(4); P1; w0(4); P1;
|
||||||
dev_err(&pi->dev, "on26: Device reset failed (%x,%x)\n", x, y);
|
}
|
||||||
|
|
||||||
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;
|
return 5;
|
||||||
pi->mode = m;
|
|
||||||
w0(pi->saved_r0);
|
|
||||||
w2(pi->saved_r2);
|
|
||||||
|
|
||||||
return 5;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void on26_read_block(struct pi_adapter *pi, char *buf, int count)
|
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:
|
||||||
switch (pi->mode) {
|
w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1;
|
||||||
|
|
||||||
case 0: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x18); P2; w0(0); P1;
|
|
||||||
udelay(10);
|
udelay(10);
|
||||||
for (k=0;k<count;k++) {
|
for (k = 0; k < count; k++) {
|
||||||
w2(6); a = r1();
|
w2(6); a = r1();
|
||||||
w2(4); b = r1();
|
w2(4); b = r1();
|
||||||
buf[k] = j44(a,b);
|
buf[k] = j44(a, b);
|
||||||
}
|
}
|
||||||
w0(2); P1; w0(8); P2;
|
w0(2); P1; w0(8); P2;
|
||||||
break;
|
break;
|
||||||
|
case 1:
|
||||||
case 1: w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1;
|
w0(1); P1; w0(1); P2; w0(2); P1; w0(0x19); P2; w0(0); P1;
|
||||||
udelay(10);
|
udelay(10);
|
||||||
for (k=0;k<count/2;k++) {
|
for (k = 0; k < count / 2; k++) {
|
||||||
w2(0x26); buf[2*k] = r0();
|
w2(0x26); buf[2 * k] = r0();
|
||||||
w2(0x24); buf[2*k+1] = r0();
|
w2(0x24); buf[2 * k + 1] = r0();
|
||||||
}
|
}
|
||||||
w0(2); P1; w0(9); P2;
|
w0(2); P1; w0(9); P2;
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
|
w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||||
w3(0); w3(0); w2(0x24);
|
w3(0); w3(0); w2(0x24);
|
||||||
udelay(10);
|
udelay(10);
|
||||||
for (k=0;k<count;k++) buf[k] = r4();
|
for (k = 0; k < count; k++)
|
||||||
w2(4);
|
buf[k] = r4();
|
||||||
break;
|
w2(4);
|
||||||
|
break;
|
||||||
case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
|
case 3:
|
||||||
w3(0); w3(0); w2(0x24);
|
w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||||
udelay(10);
|
w3(0); w3(0); w2(0x24);
|
||||||
for (k=0;k<count/2;k++) ((u16 *)buf)[k] = r4w();
|
udelay(10);
|
||||||
w2(4);
|
for (k = 0; k < count / 2; k++)
|
||||||
break;
|
((u16 *)buf)[k] = r4w();
|
||||||
|
w2(4);
|
||||||
case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
|
break;
|
||||||
w3(0); w3(0); w2(0x24);
|
case 4:
|
||||||
udelay(10);
|
w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||||
for (k=0;k<count/4;k++) ((u32 *)buf)[k] = r4l();
|
w3(0); w3(0); w2(0x24);
|
||||||
w2(4);
|
udelay(10);
|
||||||
break;
|
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)
|
static void on26_write_block(struct pi_adapter *pi, char *buf, int count)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
{ int k;
|
switch (pi->mode) {
|
||||||
|
case 0:
|
||||||
switch (pi->mode) {
|
case 1:
|
||||||
|
w0(1); P1; w0(1); P2;
|
||||||
case 0:
|
w0(2); P1; w0(0x18 + pi->mode); P2; w0(0); P1;
|
||||||
case 1: w0(1); P1; w0(1); P2;
|
|
||||||
w0(2); P1; w0(0x18+pi->mode); P2; w0(0); P1;
|
|
||||||
udelay(10);
|
udelay(10);
|
||||||
for (k=0;k<count/2;k++) {
|
for (k = 0; k < count / 2; k++) {
|
||||||
w2(5); w0(buf[2*k]);
|
w2(5); w0(buf[2 * k]);
|
||||||
w2(7); w0(buf[2*k+1]);
|
w2(7); w0(buf[2 * k + 1]);
|
||||||
}
|
}
|
||||||
w2(5); w2(4);
|
w2(5); w2(4);
|
||||||
w0(2); P1; w0(8+pi->mode); P2;
|
w0(2); P1; w0(8 + pi->mode); P2;
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
case 2: w3(1); w3(1); w2(5); w4(1); w2(4);
|
w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||||
w3(0); w3(0); w2(0xc5);
|
w3(0); w3(0); w2(0xc5);
|
||||||
udelay(10);
|
udelay(10);
|
||||||
for (k=0;k<count;k++) w4(buf[k]);
|
for (k = 0; k < count; k++)
|
||||||
|
w4(buf[k]);
|
||||||
w2(0xc4);
|
w2(0xc4);
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
case 3: w3(1); w3(1); w2(5); w4(1); w2(4);
|
w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||||
w3(0); w3(0); w2(0xc5);
|
w3(0); w3(0); w2(0xc5);
|
||||||
udelay(10);
|
udelay(10);
|
||||||
for (k=0;k<count/2;k++) w4w(((u16 *)buf)[k]);
|
for (k = 0; k < count / 2; k++)
|
||||||
w2(0xc4);
|
w4w(((u16 *)buf)[k]);
|
||||||
break;
|
w2(0xc4);
|
||||||
|
break;
|
||||||
case 4: w3(1); w3(1); w2(5); w4(1); w2(4);
|
case 4:
|
||||||
w3(0); w3(0); w2(0xc5);
|
w3(1); w3(1); w2(5); w4(1); w2(4);
|
||||||
udelay(10);
|
w3(0); w3(0); w2(0xc5);
|
||||||
for (k=0;k<count/4;k++) w4l(((u32 *)buf)[k]);
|
udelay(10);
|
||||||
w2(0xc4);
|
for (k = 0; k < count / 4; k++)
|
||||||
break;
|
w4l(((u32 *)buf)[k]);
|
||||||
|
w2(0xc4);
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void on26_log_adapter(struct pi_adapter *pi)
|
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",
|
dev_info(&pi->dev,
|
||||||
"EPP-16","EPP-32"};
|
"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 = {
|
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 = {
|
static struct platform_driver pata_platform_driver = {
|
||||||
.probe = pata_platform_probe,
|
.probe = pata_platform_probe,
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
},
|
},
|
||||||
|
@ -614,7 +614,7 @@ static SIMPLE_DEV_PM_OPS(ahci_highbank_pm_ops,
|
|||||||
ahci_highbank_suspend, ahci_highbank_resume);
|
ahci_highbank_suspend, ahci_highbank_resume);
|
||||||
|
|
||||||
static struct platform_driver ahci_highbank_driver = {
|
static struct platform_driver ahci_highbank_driver = {
|
||||||
.remove = ata_platform_remove_one,
|
.remove_new = ata_platform_remove_one,
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "highbank-ahci",
|
.name = "highbank-ahci",
|
||||||
.of_match_table = ahci_of_match,
|
.of_match_table = ahci_of_match,
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <scsi/scsi.h>
|
#include <scsi/scsi.h>
|
||||||
#include <linux/libata.h>
|
#include <linux/libata.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
|
||||||
#define DRV_NAME "sata_svw"
|
#define DRV_NAME "sata_svw"
|
||||||
#define DRV_VERSION "2.3"
|
#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 */
|
/* Match it to a port node */
|
||||||
index = (ap == ap->host->ports[0]) ? 0 : 1;
|
index = (ap == ap->host->ports[0]) ? 0 : 1;
|
||||||
for (np = np->child; np != NULL; np = np->sibling) {
|
for (np = np->child; np != NULL; np = np->sibling) {
|
||||||
const u32 *reg = of_get_property(np, "reg", NULL);
|
u64 reg;
|
||||||
if (!reg)
|
|
||||||
|
if (of_property_read_reg(np, 0, ®, NULL))
|
||||||
continue;
|
continue;
|
||||||
if (index == *reg) {
|
if (index == reg) {
|
||||||
seq_printf(m, "devspec: %pOF\n", np);
|
seq_printf(m, "devspec: %pOF\n", np);
|
||||||
break;
|
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);
|
struct domain_device *dev = sdev_to_domain_dev(sdev);
|
||||||
|
|
||||||
if (dev_is_sata(dev))
|
if (dev_is_sata(dev))
|
||||||
return ata_change_queue_depth(dev->sata_dev.ap,
|
return ata_change_queue_depth(dev->sata_dev.ap, sdev, depth);
|
||||||
sas_to_ata_dev(dev), sdev, depth);
|
|
||||||
|
|
||||||
if (!sdev->tagged_supported)
|
if (!sdev->tagged_supported)
|
||||||
depth = 1;
|
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 void ata_scsi_slave_destroy(struct scsi_device *sdev);
|
||||||
extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
|
extern int ata_scsi_change_queue_depth(struct scsi_device *sdev,
|
||||||
int queue_depth);
|
int queue_depth);
|
||||||
extern int ata_change_queue_depth(struct ata_port *ap, struct ata_device *dev,
|
extern int ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
|
||||||
struct scsi_device *sdev, int queue_depth);
|
int queue_depth);
|
||||||
extern struct ata_device *ata_dev_pair(struct ata_device *adev);
|
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 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);
|
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;
|
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
|
* ACPI - drivers/ata/libata-acpi.c
|
||||||
|
Loading…
x
Reference in New Issue
Block a user