162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * pata_netcell.c - Netcell PATA driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * (c) 2006 Red Hat 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/kernel.h> 962306a36Sopenharmony_ci#include <linux/module.h> 1062306a36Sopenharmony_ci#include <linux/pci.h> 1162306a36Sopenharmony_ci#include <linux/blkdev.h> 1262306a36Sopenharmony_ci#include <linux/delay.h> 1362306a36Sopenharmony_ci#include <linux/device.h> 1462306a36Sopenharmony_ci#include <scsi/scsi_host.h> 1562306a36Sopenharmony_ci#include <linux/libata.h> 1662306a36Sopenharmony_ci#include <linux/ata.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#define DRV_NAME "pata_netcell" 1962306a36Sopenharmony_ci#define DRV_VERSION "0.1.7" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* No PIO or DMA methods needed for this device */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic unsigned int netcell_read_id(struct ata_device *adev, 2462306a36Sopenharmony_ci struct ata_taskfile *tf, __le16 *id) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci unsigned int err_mask = ata_do_dev_read_id(adev, tf, id); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci /* Firmware forgets to mark words 85-87 valid */ 2962306a36Sopenharmony_ci if (err_mask == 0) 3062306a36Sopenharmony_ci id[ATA_ID_CSF_DEFAULT] |= cpu_to_le16(0x4000); 3162306a36Sopenharmony_ci return err_mask; 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic const struct scsi_host_template netcell_sht = { 3562306a36Sopenharmony_ci ATA_BMDMA_SHT(DRV_NAME), 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic struct ata_port_operations netcell_ops = { 3962306a36Sopenharmony_ci .inherits = &ata_bmdma_port_ops, 4062306a36Sopenharmony_ci .cable_detect = ata_cable_80wire, 4162306a36Sopenharmony_ci .read_id = netcell_read_id, 4262306a36Sopenharmony_ci}; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci/** 4662306a36Sopenharmony_ci * netcell_init_one - Register Netcell ATA PCI device with kernel services 4762306a36Sopenharmony_ci * @pdev: PCI device to register 4862306a36Sopenharmony_ci * @ent: Entry in netcell_pci_tbl matching with @pdev 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * Called from kernel PCI layer. 5162306a36Sopenharmony_ci * 5262306a36Sopenharmony_ci * LOCKING: 5362306a36Sopenharmony_ci * Inherited from PCI layer (may sleep). 5462306a36Sopenharmony_ci * 5562306a36Sopenharmony_ci * RETURNS: 5662306a36Sopenharmony_ci * Zero on success, or -ERRNO value. 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_cistatic int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) 6062306a36Sopenharmony_ci{ 6162306a36Sopenharmony_ci static const struct ata_port_info info = { 6262306a36Sopenharmony_ci .flags = ATA_FLAG_SLAVE_POSS, 6362306a36Sopenharmony_ci /* Actually we don't really care about these as the 6462306a36Sopenharmony_ci firmware deals with it */ 6562306a36Sopenharmony_ci .pio_mask = ATA_PIO4, 6662306a36Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 6762306a36Sopenharmony_ci .udma_mask = ATA_UDMA5, /* UDMA 133 */ 6862306a36Sopenharmony_ci .port_ops = &netcell_ops, 6962306a36Sopenharmony_ci }; 7062306a36Sopenharmony_ci const struct ata_port_info *port_info[] = { &info, NULL }; 7162306a36Sopenharmony_ci int rc; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci ata_print_version_once(&pdev->dev, DRV_VERSION); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci rc = pcim_enable_device(pdev); 7662306a36Sopenharmony_ci if (rc) 7762306a36Sopenharmony_ci return rc; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci /* Any chip specific setup/optimisation/messages here */ 8062306a36Sopenharmony_ci ata_pci_bmdma_clear_simplex(pdev); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* And let the library code do the work */ 8362306a36Sopenharmony_ci return ata_pci_bmdma_init_one(pdev, port_info, &netcell_sht, NULL, 0); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic const struct pci_device_id netcell_pci_tbl[] = { 8762306a36Sopenharmony_ci { PCI_VDEVICE(NETCELL, PCI_DEVICE_ID_REVOLUTION), }, 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci { } /* terminate list */ 9062306a36Sopenharmony_ci}; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic struct pci_driver netcell_pci_driver = { 9362306a36Sopenharmony_ci .name = DRV_NAME, 9462306a36Sopenharmony_ci .id_table = netcell_pci_tbl, 9562306a36Sopenharmony_ci .probe = netcell_init_one, 9662306a36Sopenharmony_ci .remove = ata_pci_remove_one, 9762306a36Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 9862306a36Sopenharmony_ci .suspend = ata_pci_device_suspend, 9962306a36Sopenharmony_ci .resume = ata_pci_device_resume, 10062306a36Sopenharmony_ci#endif 10162306a36Sopenharmony_ci}; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cimodule_pci_driver(netcell_pci_driver); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ciMODULE_AUTHOR("Alan Cox"); 10662306a36Sopenharmony_ciMODULE_DESCRIPTION("SCSI low-level driver for Netcell PATA RAID"); 10762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 10862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(pci, netcell_pci_tbl); 10962306a36Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 110