18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * pata_netcell.c - Netcell PATA driver 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * (c) 2006 Red Hat 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/kernel.h> 98c2ecf20Sopenharmony_ci#include <linux/module.h> 108c2ecf20Sopenharmony_ci#include <linux/pci.h> 118c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 128c2ecf20Sopenharmony_ci#include <linux/delay.h> 138c2ecf20Sopenharmony_ci#include <linux/device.h> 148c2ecf20Sopenharmony_ci#include <scsi/scsi_host.h> 158c2ecf20Sopenharmony_ci#include <linux/libata.h> 168c2ecf20Sopenharmony_ci#include <linux/ata.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#define DRV_NAME "pata_netcell" 198c2ecf20Sopenharmony_ci#define DRV_VERSION "0.1.7" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* No PIO or DMA methods needed for this device */ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_cistatic unsigned int netcell_read_id(struct ata_device *adev, 248c2ecf20Sopenharmony_ci struct ata_taskfile *tf, u16 *id) 258c2ecf20Sopenharmony_ci{ 268c2ecf20Sopenharmony_ci unsigned int err_mask = ata_do_dev_read_id(adev, tf, id); 278c2ecf20Sopenharmony_ci /* Firmware forgets to mark words 85-87 valid */ 288c2ecf20Sopenharmony_ci if (err_mask == 0) 298c2ecf20Sopenharmony_ci id[ATA_ID_CSF_DEFAULT] |= 0x4000; 308c2ecf20Sopenharmony_ci return err_mask; 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic struct scsi_host_template netcell_sht = { 348c2ecf20Sopenharmony_ci ATA_BMDMA_SHT(DRV_NAME), 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic struct ata_port_operations netcell_ops = { 388c2ecf20Sopenharmony_ci .inherits = &ata_bmdma_port_ops, 398c2ecf20Sopenharmony_ci .cable_detect = ata_cable_80wire, 408c2ecf20Sopenharmony_ci .read_id = netcell_read_id, 418c2ecf20Sopenharmony_ci}; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/** 458c2ecf20Sopenharmony_ci * netcell_init_one - Register Netcell ATA PCI device with kernel services 468c2ecf20Sopenharmony_ci * @pdev: PCI device to register 478c2ecf20Sopenharmony_ci * @ent: Entry in netcell_pci_tbl matching with @pdev 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci * Called from kernel PCI layer. 508c2ecf20Sopenharmony_ci * 518c2ecf20Sopenharmony_ci * LOCKING: 528c2ecf20Sopenharmony_ci * Inherited from PCI layer (may sleep). 538c2ecf20Sopenharmony_ci * 548c2ecf20Sopenharmony_ci * RETURNS: 558c2ecf20Sopenharmony_ci * Zero on success, or -ERRNO value. 568c2ecf20Sopenharmony_ci */ 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_cistatic int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) 598c2ecf20Sopenharmony_ci{ 608c2ecf20Sopenharmony_ci static const struct ata_port_info info = { 618c2ecf20Sopenharmony_ci .flags = ATA_FLAG_SLAVE_POSS, 628c2ecf20Sopenharmony_ci /* Actually we don't really care about these as the 638c2ecf20Sopenharmony_ci firmware deals with it */ 648c2ecf20Sopenharmony_ci .pio_mask = ATA_PIO4, 658c2ecf20Sopenharmony_ci .mwdma_mask = ATA_MWDMA2, 668c2ecf20Sopenharmony_ci .udma_mask = ATA_UDMA5, /* UDMA 133 */ 678c2ecf20Sopenharmony_ci .port_ops = &netcell_ops, 688c2ecf20Sopenharmony_ci }; 698c2ecf20Sopenharmony_ci const struct ata_port_info *port_info[] = { &info, NULL }; 708c2ecf20Sopenharmony_ci int rc; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci ata_print_version_once(&pdev->dev, DRV_VERSION); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci rc = pcim_enable_device(pdev); 758c2ecf20Sopenharmony_ci if (rc) 768c2ecf20Sopenharmony_ci return rc; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci /* Any chip specific setup/optimisation/messages here */ 798c2ecf20Sopenharmony_ci ata_pci_bmdma_clear_simplex(pdev); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* And let the library code do the work */ 828c2ecf20Sopenharmony_ci return ata_pci_bmdma_init_one(pdev, port_info, &netcell_sht, NULL, 0); 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic const struct pci_device_id netcell_pci_tbl[] = { 868c2ecf20Sopenharmony_ci { PCI_VDEVICE(NETCELL, PCI_DEVICE_ID_REVOLUTION), }, 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci { } /* terminate list */ 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic struct pci_driver netcell_pci_driver = { 928c2ecf20Sopenharmony_ci .name = DRV_NAME, 938c2ecf20Sopenharmony_ci .id_table = netcell_pci_tbl, 948c2ecf20Sopenharmony_ci .probe = netcell_init_one, 958c2ecf20Sopenharmony_ci .remove = ata_pci_remove_one, 968c2ecf20Sopenharmony_ci#ifdef CONFIG_PM_SLEEP 978c2ecf20Sopenharmony_ci .suspend = ata_pci_device_suspend, 988c2ecf20Sopenharmony_ci .resume = ata_pci_device_resume, 998c2ecf20Sopenharmony_ci#endif 1008c2ecf20Sopenharmony_ci}; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cimodule_pci_driver(netcell_pci_driver); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ciMODULE_AUTHOR("Alan Cox"); 1058c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("SCSI low-level driver for Netcell PATA RAID"); 1068c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1078c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, netcell_pci_tbl); 1088c2ecf20Sopenharmony_ciMODULE_VERSION(DRV_VERSION); 109