1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663 |
- /*
- * sata_nv.c - NVIDIA nForce SATA
- *
- * Copyright 2004 NVIDIA Corp. All rights reserved.
- * Copyright 2004 Andrew Chew
- *
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *
- * libata documentation is available via 'make {ps|pdf}docs',
- * as Documentation/DocBook/libata.*
- *
- * No hardware documentation available outside of NVIDIA.
- * This driver programs the NVIDIA SATA controller in a similar
- * fashion as with other PCI IDE BMDMA controllers, with a few
- * NV-specific details such as register offsets, SATA phy location,
- * hotplug info, etc.
- *
- * CK804/MCP04 controllers support an alternate programming interface
- * similar to the ADMA specification (with some modifications).
- * This allows the use of NCQ. Non-DMA-mapped ATA commands are still
- * sent through the legacy interface.
- *
- */
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/pci.h>
- #include <linux/init.h>
- #include <linux/blkdev.h>
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- #include <linux/device.h>
- #include <scsi/scsi_host.h>
- #include <scsi/scsi_device.h>
- #include <linux/libata.h>
- #define DRV_NAME "sata_nv"
- #define DRV_VERSION "3.3"
- #define NV_ADMA_DMA_BOUNDARY 0xffffffffUL
- enum {
- NV_MMIO_BAR = 5,
- NV_PORTS = 2,
- NV_PIO_MASK = 0x1f,
- NV_MWDMA_MASK = 0x07,
- NV_UDMA_MASK = 0x7f,
- NV_PORT0_SCR_REG_OFFSET = 0x00,
- NV_PORT1_SCR_REG_OFFSET = 0x40,
- /* INT_STATUS/ENABLE */
- NV_INT_STATUS = 0x10,
- NV_INT_ENABLE = 0x11,
- NV_INT_STATUS_CK804 = 0x440,
- NV_INT_ENABLE_CK804 = 0x441,
- /* INT_STATUS/ENABLE bits */
- NV_INT_DEV = 0x01,
- NV_INT_PM = 0x02,
- NV_INT_ADDED = 0x04,
- NV_INT_REMOVED = 0x08,
- NV_INT_PORT_SHIFT = 4, /* each port occupies 4 bits */
- NV_INT_ALL = 0x0f,
- NV_INT_MASK = NV_INT_DEV |
- NV_INT_ADDED | NV_INT_REMOVED,
- /* INT_CONFIG */
- NV_INT_CONFIG = 0x12,
- NV_INT_CONFIG_METHD = 0x01, // 0 = INT, 1 = SMI
- // For PCI config register 20
- NV_MCP_SATA_CFG_20 = 0x50,
- NV_MCP_SATA_CFG_20_SATA_SPACE_EN = 0x04,
- NV_MCP_SATA_CFG_20_PORT0_EN = (1 << 17),
- NV_MCP_SATA_CFG_20_PORT1_EN = (1 << 16),
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN = (1 << 14),
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN = (1 << 12),
- NV_ADMA_MAX_CPBS = 32,
- NV_ADMA_CPB_SZ = 128,
- NV_ADMA_APRD_SZ = 16,
- NV_ADMA_SGTBL_LEN = (1024 - NV_ADMA_CPB_SZ) /
- NV_ADMA_APRD_SZ,
- NV_ADMA_SGTBL_TOTAL_LEN = NV_ADMA_SGTBL_LEN + 5,
- NV_ADMA_SGTBL_SZ = NV_ADMA_SGTBL_LEN * NV_ADMA_APRD_SZ,
- NV_ADMA_PORT_PRIV_DMA_SZ = NV_ADMA_MAX_CPBS *
- (NV_ADMA_CPB_SZ + NV_ADMA_SGTBL_SZ),
- /* BAR5 offset to ADMA general registers */
- NV_ADMA_GEN = 0x400,
- NV_ADMA_GEN_CTL = 0x00,
- NV_ADMA_NOTIFIER_CLEAR = 0x30,
- /* BAR5 offset to ADMA ports */
- NV_ADMA_PORT = 0x480,
- /* size of ADMA port register space */
- NV_ADMA_PORT_SIZE = 0x100,
- /* ADMA port registers */
- NV_ADMA_CTL = 0x40,
- NV_ADMA_CPB_COUNT = 0x42,
- NV_ADMA_NEXT_CPB_IDX = 0x43,
- NV_ADMA_STAT = 0x44,
- NV_ADMA_CPB_BASE_LOW = 0x48,
- NV_ADMA_CPB_BASE_HIGH = 0x4C,
- NV_ADMA_APPEND = 0x50,
- NV_ADMA_NOTIFIER = 0x68,
- NV_ADMA_NOTIFIER_ERROR = 0x6C,
- /* NV_ADMA_CTL register bits */
- NV_ADMA_CTL_HOTPLUG_IEN = (1 << 0),
- NV_ADMA_CTL_CHANNEL_RESET = (1 << 5),
- NV_ADMA_CTL_GO = (1 << 7),
- NV_ADMA_CTL_AIEN = (1 << 8),
- NV_ADMA_CTL_READ_NON_COHERENT = (1 << 11),
- NV_ADMA_CTL_WRITE_NON_COHERENT = (1 << 12),
- /* CPB response flag bits */
- NV_CPB_RESP_DONE = (1 << 0),
- NV_CPB_RESP_ATA_ERR = (1 << 3),
- NV_CPB_RESP_CMD_ERR = (1 << 4),
- NV_CPB_RESP_CPB_ERR = (1 << 7),
- /* CPB control flag bits */
- NV_CPB_CTL_CPB_VALID = (1 << 0),
- NV_CPB_CTL_QUEUE = (1 << 1),
- NV_CPB_CTL_APRD_VALID = (1 << 2),
- NV_CPB_CTL_IEN = (1 << 3),
- NV_CPB_CTL_FPDMA = (1 << 4),
- /* APRD flags */
- NV_APRD_WRITE = (1 << 1),
- NV_APRD_END = (1 << 2),
- NV_APRD_CONT = (1 << 3),
- /* NV_ADMA_STAT flags */
- NV_ADMA_STAT_TIMEOUT = (1 << 0),
- NV_ADMA_STAT_HOTUNPLUG = (1 << 1),
- NV_ADMA_STAT_HOTPLUG = (1 << 2),
- NV_ADMA_STAT_CPBERR = (1 << 4),
- NV_ADMA_STAT_SERROR = (1 << 5),
- NV_ADMA_STAT_CMD_COMPLETE = (1 << 6),
- NV_ADMA_STAT_IDLE = (1 << 8),
- NV_ADMA_STAT_LEGACY = (1 << 9),
- NV_ADMA_STAT_STOPPED = (1 << 10),
- NV_ADMA_STAT_DONE = (1 << 12),
- NV_ADMA_STAT_ERR = NV_ADMA_STAT_CPBERR |
- NV_ADMA_STAT_TIMEOUT,
- /* port flags */
- NV_ADMA_PORT_REGISTER_MODE = (1 << 0),
- NV_ADMA_ATAPI_SETUP_COMPLETE = (1 << 1),
- };
- /* ADMA Physical Region Descriptor - one SG segment */
- struct nv_adma_prd {
- __le64 addr;
- __le32 len;
- u8 flags;
- u8 packet_len;
- __le16 reserved;
- };
- enum nv_adma_regbits {
- CMDEND = (1 << 15), /* end of command list */
- WNB = (1 << 14), /* wait-not-BSY */
- IGN = (1 << 13), /* ignore this entry */
- CS1n = (1 << (4 + 8)), /* std. PATA signals follow... */
- DA2 = (1 << (2 + 8)),
- DA1 = (1 << (1 + 8)),
- DA0 = (1 << (0 + 8)),
- };
- /* ADMA Command Parameter Block
- The first 5 SG segments are stored inside the Command Parameter Block itself.
- If there are more than 5 segments the remainder are stored in a separate
- memory area indicated by next_aprd. */
- struct nv_adma_cpb {
- u8 resp_flags; /* 0 */
- u8 reserved1; /* 1 */
- u8 ctl_flags; /* 2 */
- /* len is length of taskfile in 64 bit words */
- u8 len; /* 3 */
- u8 tag; /* 4 */
- u8 next_cpb_idx; /* 5 */
- __le16 reserved2; /* 6-7 */
- __le16 tf[12]; /* 8-31 */
- struct nv_adma_prd aprd[5]; /* 32-111 */
- __le64 next_aprd; /* 112-119 */
- __le64 reserved3; /* 120-127 */
- };
- struct nv_adma_port_priv {
- struct nv_adma_cpb *cpb;
- dma_addr_t cpb_dma;
- struct nv_adma_prd *aprd;
- dma_addr_t aprd_dma;
- void __iomem * ctl_block;
- void __iomem * gen_block;
- void __iomem * notifier_clear_block;
- u8 flags;
- };
- struct nv_host_priv {
- unsigned long type;
- };
- #define NV_ADMA_CHECK_INTR(GCTL, PORT) ((GCTL) & ( 1 << (19 + (12 * (PORT)))))
- static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
- static void nv_remove_one (struct pci_dev *pdev);
- static int nv_pci_device_resume(struct pci_dev *pdev);
- static void nv_ck804_host_stop(struct ata_host *host);
- static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance);
- static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance);
- static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance);
- static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg);
- static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
- static void nv_nf2_freeze(struct ata_port *ap);
- static void nv_nf2_thaw(struct ata_port *ap);
- static void nv_ck804_freeze(struct ata_port *ap);
- static void nv_ck804_thaw(struct ata_port *ap);
- static void nv_error_handler(struct ata_port *ap);
- static int nv_adma_slave_config(struct scsi_device *sdev);
- static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc);
- static void nv_adma_qc_prep(struct ata_queued_cmd *qc);
- static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc);
- static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance);
- static void nv_adma_irq_clear(struct ata_port *ap);
- static int nv_adma_port_start(struct ata_port *ap);
- static void nv_adma_port_stop(struct ata_port *ap);
- static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg);
- static int nv_adma_port_resume(struct ata_port *ap);
- static void nv_adma_error_handler(struct ata_port *ap);
- static void nv_adma_host_stop(struct ata_host *host);
- static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc);
- static void nv_adma_bmdma_start(struct ata_queued_cmd *qc);
- static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc);
- static u8 nv_adma_bmdma_status(struct ata_port *ap);
- enum nv_host_type
- {
- GENERIC,
- NFORCE2,
- NFORCE3 = NFORCE2, /* NF2 == NF3 as far as sata_nv is concerned */
- CK804,
- ADMA
- };
- static const struct pci_device_id nv_pci_tbl[] = {
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA), NFORCE2 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA), NFORCE3 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2), NFORCE3 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA), CK804 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2), CK804 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA), CK804 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2), CK804 },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA), GENERIC },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2), GENERIC },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA), GENERIC },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2), GENERIC },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA), GENERIC },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2), GENERIC },
- { PCI_VDEVICE(NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3), GENERIC },
- { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
- PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_STORAGE_IDE<<8, 0xffff00, GENERIC },
- { PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID,
- PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_STORAGE_RAID<<8, 0xffff00, GENERIC },
- { } /* terminate list */
- };
- static struct pci_driver nv_pci_driver = {
- .name = DRV_NAME,
- .id_table = nv_pci_tbl,
- .probe = nv_init_one,
- .suspend = ata_pci_device_suspend,
- .resume = nv_pci_device_resume,
- .remove = nv_remove_one,
- };
- static struct scsi_host_template nv_sht = {
- .module = THIS_MODULE,
- .name = DRV_NAME,
- .ioctl = ata_scsi_ioctl,
- .queuecommand = ata_scsi_queuecmd,
- .can_queue = ATA_DEF_QUEUE,
- .this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = LIBATA_MAX_PRD,
- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
- .emulated = ATA_SHT_EMULATED,
- .use_clustering = ATA_SHT_USE_CLUSTERING,
- .proc_name = DRV_NAME,
- .dma_boundary = ATA_DMA_BOUNDARY,
- .slave_configure = ata_scsi_slave_config,
- .slave_destroy = ata_scsi_slave_destroy,
- .bios_param = ata_std_bios_param,
- .suspend = ata_scsi_device_suspend,
- .resume = ata_scsi_device_resume,
- };
- static struct scsi_host_template nv_adma_sht = {
- .module = THIS_MODULE,
- .name = DRV_NAME,
- .ioctl = ata_scsi_ioctl,
- .queuecommand = ata_scsi_queuecmd,
- .can_queue = NV_ADMA_MAX_CPBS,
- .this_id = ATA_SHT_THIS_ID,
- .sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN,
- .cmd_per_lun = ATA_SHT_CMD_PER_LUN,
- .emulated = ATA_SHT_EMULATED,
- .use_clustering = ATA_SHT_USE_CLUSTERING,
- .proc_name = DRV_NAME,
- .dma_boundary = NV_ADMA_DMA_BOUNDARY,
- .slave_configure = nv_adma_slave_config,
- .slave_destroy = ata_scsi_slave_destroy,
- .bios_param = ata_std_bios_param,
- .suspend = ata_scsi_device_suspend,
- .resume = ata_scsi_device_resume,
- };
- static const struct ata_port_operations nv_generic_ops = {
- .port_disable = ata_port_disable,
- .tf_load = ata_tf_load,
- .tf_read = ata_tf_read,
- .exec_command = ata_exec_command,
- .check_status = ata_check_status,
- .dev_select = ata_std_dev_select,
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
- .bmdma_stop = ata_bmdma_stop,
- .bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
- .freeze = ata_bmdma_freeze,
- .thaw = ata_bmdma_thaw,
- .error_handler = nv_error_handler,
- .post_internal_cmd = ata_bmdma_post_internal_cmd,
- .data_xfer = ata_data_xfer,
- .irq_handler = nv_generic_interrupt,
- .irq_clear = ata_bmdma_irq_clear,
- .irq_on = ata_irq_on,
- .irq_ack = ata_irq_ack,
- .scr_read = nv_scr_read,
- .scr_write = nv_scr_write,
- .port_start = ata_port_start,
- };
- static const struct ata_port_operations nv_nf2_ops = {
- .port_disable = ata_port_disable,
- .tf_load = ata_tf_load,
- .tf_read = ata_tf_read,
- .exec_command = ata_exec_command,
- .check_status = ata_check_status,
- .dev_select = ata_std_dev_select,
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
- .bmdma_stop = ata_bmdma_stop,
- .bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
- .freeze = nv_nf2_freeze,
- .thaw = nv_nf2_thaw,
- .error_handler = nv_error_handler,
- .post_internal_cmd = ata_bmdma_post_internal_cmd,
- .data_xfer = ata_data_xfer,
- .irq_handler = nv_nf2_interrupt,
- .irq_clear = ata_bmdma_irq_clear,
- .irq_on = ata_irq_on,
- .irq_ack = ata_irq_ack,
- .scr_read = nv_scr_read,
- .scr_write = nv_scr_write,
- .port_start = ata_port_start,
- };
- static const struct ata_port_operations nv_ck804_ops = {
- .port_disable = ata_port_disable,
- .tf_load = ata_tf_load,
- .tf_read = ata_tf_read,
- .exec_command = ata_exec_command,
- .check_status = ata_check_status,
- .dev_select = ata_std_dev_select,
- .bmdma_setup = ata_bmdma_setup,
- .bmdma_start = ata_bmdma_start,
- .bmdma_stop = ata_bmdma_stop,
- .bmdma_status = ata_bmdma_status,
- .qc_prep = ata_qc_prep,
- .qc_issue = ata_qc_issue_prot,
- .freeze = nv_ck804_freeze,
- .thaw = nv_ck804_thaw,
- .error_handler = nv_error_handler,
- .post_internal_cmd = ata_bmdma_post_internal_cmd,
- .data_xfer = ata_data_xfer,
- .irq_handler = nv_ck804_interrupt,
- .irq_clear = ata_bmdma_irq_clear,
- .irq_on = ata_irq_on,
- .irq_ack = ata_irq_ack,
- .scr_read = nv_scr_read,
- .scr_write = nv_scr_write,
- .port_start = ata_port_start,
- .host_stop = nv_ck804_host_stop,
- };
- static const struct ata_port_operations nv_adma_ops = {
- .port_disable = ata_port_disable,
- .tf_load = ata_tf_load,
- .tf_read = ata_tf_read,
- .check_atapi_dma = nv_adma_check_atapi_dma,
- .exec_command = ata_exec_command,
- .check_status = ata_check_status,
- .dev_select = ata_std_dev_select,
- .bmdma_setup = nv_adma_bmdma_setup,
- .bmdma_start = nv_adma_bmdma_start,
- .bmdma_stop = nv_adma_bmdma_stop,
- .bmdma_status = nv_adma_bmdma_status,
- .qc_prep = nv_adma_qc_prep,
- .qc_issue = nv_adma_qc_issue,
- .freeze = nv_ck804_freeze,
- .thaw = nv_ck804_thaw,
- .error_handler = nv_adma_error_handler,
- .post_internal_cmd = nv_adma_bmdma_stop,
- .data_xfer = ata_data_xfer,
- .irq_handler = nv_adma_interrupt,
- .irq_clear = nv_adma_irq_clear,
- .irq_on = ata_irq_on,
- .irq_ack = ata_irq_ack,
- .scr_read = nv_scr_read,
- .scr_write = nv_scr_write,
- .port_start = nv_adma_port_start,
- .port_stop = nv_adma_port_stop,
- .port_suspend = nv_adma_port_suspend,
- .port_resume = nv_adma_port_resume,
- .host_stop = nv_adma_host_stop,
- };
- static struct ata_port_info nv_port_info[] = {
- /* generic */
- {
- .sht = &nv_sht,
- .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_HRST_TO_RESUME,
- .pio_mask = NV_PIO_MASK,
- .mwdma_mask = NV_MWDMA_MASK,
- .udma_mask = NV_UDMA_MASK,
- .port_ops = &nv_generic_ops,
- },
- /* nforce2/3 */
- {
- .sht = &nv_sht,
- .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_HRST_TO_RESUME,
- .pio_mask = NV_PIO_MASK,
- .mwdma_mask = NV_MWDMA_MASK,
- .udma_mask = NV_UDMA_MASK,
- .port_ops = &nv_nf2_ops,
- },
- /* ck804 */
- {
- .sht = &nv_sht,
- .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_HRST_TO_RESUME,
- .pio_mask = NV_PIO_MASK,
- .mwdma_mask = NV_MWDMA_MASK,
- .udma_mask = NV_UDMA_MASK,
- .port_ops = &nv_ck804_ops,
- },
- /* ADMA */
- {
- .sht = &nv_adma_sht,
- .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
- ATA_FLAG_HRST_TO_RESUME |
- ATA_FLAG_MMIO | ATA_FLAG_NCQ,
- .pio_mask = NV_PIO_MASK,
- .mwdma_mask = NV_MWDMA_MASK,
- .udma_mask = NV_UDMA_MASK,
- .port_ops = &nv_adma_ops,
- },
- };
- MODULE_AUTHOR("NVIDIA");
- MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
- MODULE_LICENSE("GPL");
- MODULE_DEVICE_TABLE(pci, nv_pci_tbl);
- MODULE_VERSION(DRV_VERSION);
- static int adma_enabled = 1;
- static void nv_adma_register_mode(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- u16 tmp, status;
- int count = 0;
- if (pp->flags & NV_ADMA_PORT_REGISTER_MODE)
- return;
- status = readw(mmio + NV_ADMA_STAT);
- while(!(status & NV_ADMA_STAT_IDLE) && count < 20) {
- ndelay(50);
- status = readw(mmio + NV_ADMA_STAT);
- count++;
- }
- if(count == 20)
- ata_port_printk(ap, KERN_WARNING,
- "timeout waiting for ADMA IDLE, stat=0x%hx\n",
- status);
- tmp = readw(mmio + NV_ADMA_CTL);
- writew(tmp & ~NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
- count = 0;
- status = readw(mmio + NV_ADMA_STAT);
- while(!(status & NV_ADMA_STAT_LEGACY) && count < 20) {
- ndelay(50);
- status = readw(mmio + NV_ADMA_STAT);
- count++;
- }
- if(count == 20)
- ata_port_printk(ap, KERN_WARNING,
- "timeout waiting for ADMA LEGACY, stat=0x%hx\n",
- status);
- pp->flags |= NV_ADMA_PORT_REGISTER_MODE;
- }
- static void nv_adma_mode(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- u16 tmp, status;
- int count = 0;
- if (!(pp->flags & NV_ADMA_PORT_REGISTER_MODE))
- return;
- WARN_ON(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE);
- tmp = readw(mmio + NV_ADMA_CTL);
- writew(tmp | NV_ADMA_CTL_GO, mmio + NV_ADMA_CTL);
- status = readw(mmio + NV_ADMA_STAT);
- while(((status & NV_ADMA_STAT_LEGACY) ||
- !(status & NV_ADMA_STAT_IDLE)) && count < 20) {
- ndelay(50);
- status = readw(mmio + NV_ADMA_STAT);
- count++;
- }
- if(count == 20)
- ata_port_printk(ap, KERN_WARNING,
- "timeout waiting for ADMA LEGACY clear and IDLE, stat=0x%hx\n",
- status);
- pp->flags &= ~NV_ADMA_PORT_REGISTER_MODE;
- }
- static int nv_adma_slave_config(struct scsi_device *sdev)
- {
- struct ata_port *ap = ata_shost_to_port(sdev->host);
- struct nv_adma_port_priv *pp = ap->private_data;
- struct pci_dev *pdev = to_pci_dev(ap->host->dev);
- u64 bounce_limit;
- unsigned long segment_boundary;
- unsigned short sg_tablesize;
- int rc;
- int adma_enable;
- u32 current_reg, new_reg, config_mask;
- rc = ata_scsi_slave_config(sdev);
- if (sdev->id >= ATA_MAX_DEVICES || sdev->channel || sdev->lun)
- /* Not a proper libata device, ignore */
- return rc;
- if (ap->device[sdev->id].class == ATA_DEV_ATAPI) {
- /*
- * NVIDIA reports that ADMA mode does not support ATAPI commands.
- * Therefore ATAPI commands are sent through the legacy interface.
- * However, the legacy interface only supports 32-bit DMA.
- * Restrict DMA parameters as required by the legacy interface
- * when an ATAPI device is connected.
- */
- bounce_limit = ATA_DMA_MASK;
- segment_boundary = ATA_DMA_BOUNDARY;
- /* Subtract 1 since an extra entry may be needed for padding, see
- libata-scsi.c */
- sg_tablesize = LIBATA_MAX_PRD - 1;
- /* Since the legacy DMA engine is in use, we need to disable ADMA
- on the port. */
- adma_enable = 0;
- nv_adma_register_mode(ap);
- }
- else {
- bounce_limit = *ap->dev->dma_mask;
- segment_boundary = NV_ADMA_DMA_BOUNDARY;
- sg_tablesize = NV_ADMA_SGTBL_TOTAL_LEN;
- adma_enable = 1;
- }
- pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, ¤t_reg);
- if(ap->port_no == 1)
- config_mask = NV_MCP_SATA_CFG_20_PORT1_EN |
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN;
- else
- config_mask = NV_MCP_SATA_CFG_20_PORT0_EN |
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN;
- if(adma_enable) {
- new_reg = current_reg | config_mask;
- pp->flags &= ~NV_ADMA_ATAPI_SETUP_COMPLETE;
- }
- else {
- new_reg = current_reg & ~config_mask;
- pp->flags |= NV_ADMA_ATAPI_SETUP_COMPLETE;
- }
- if(current_reg != new_reg)
- pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, new_reg);
- blk_queue_bounce_limit(sdev->request_queue, bounce_limit);
- blk_queue_segment_boundary(sdev->request_queue, segment_boundary);
- blk_queue_max_hw_segments(sdev->request_queue, sg_tablesize);
- ata_port_printk(ap, KERN_INFO,
- "bounce limit 0x%llX, segment boundary 0x%lX, hw segs %hu\n",
- (unsigned long long)bounce_limit, segment_boundary, sg_tablesize);
- return rc;
- }
- static int nv_adma_check_atapi_dma(struct ata_queued_cmd *qc)
- {
- struct nv_adma_port_priv *pp = qc->ap->private_data;
- return !(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE);
- }
- static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
- {
- unsigned int idx = 0;
- cpb[idx++] = cpu_to_le16((ATA_REG_DEVICE << 8) | tf->device | WNB);
- if ((tf->flags & ATA_TFLAG_LBA48) == 0) {
- cpb[idx++] = cpu_to_le16(IGN);
- cpb[idx++] = cpu_to_le16(IGN);
- cpb[idx++] = cpu_to_le16(IGN);
- cpb[idx++] = cpu_to_le16(IGN);
- cpb[idx++] = cpu_to_le16(IGN);
- }
- else {
- cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->hob_feature);
- cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->hob_nsect);
- cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->hob_lbal);
- cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->hob_lbam);
- cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->hob_lbah);
- }
- cpb[idx++] = cpu_to_le16((ATA_REG_ERR << 8) | tf->feature);
- cpb[idx++] = cpu_to_le16((ATA_REG_NSECT << 8) | tf->nsect);
- cpb[idx++] = cpu_to_le16((ATA_REG_LBAL << 8) | tf->lbal);
- cpb[idx++] = cpu_to_le16((ATA_REG_LBAM << 8) | tf->lbam);
- cpb[idx++] = cpu_to_le16((ATA_REG_LBAH << 8) | tf->lbah);
- cpb[idx++] = cpu_to_le16((ATA_REG_CMD << 8) | tf->command | CMDEND);
- return idx;
- }
- static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- u8 flags = pp->cpb[cpb_num].resp_flags;
- VPRINTK("CPB %d, flags=0x%x\n", cpb_num, flags);
- if (unlikely((force_err ||
- flags & (NV_CPB_RESP_ATA_ERR |
- NV_CPB_RESP_CMD_ERR |
- NV_CPB_RESP_CPB_ERR)))) {
- struct ata_eh_info *ehi = &ap->eh_info;
- int freeze = 0;
- ata_ehi_clear_desc(ehi);
- ata_ehi_push_desc(ehi, "CPB resp_flags 0x%x", flags );
- if (flags & NV_CPB_RESP_ATA_ERR) {
- ata_ehi_push_desc(ehi, ": ATA error");
- ehi->err_mask |= AC_ERR_DEV;
- } else if (flags & NV_CPB_RESP_CMD_ERR) {
- ata_ehi_push_desc(ehi, ": CMD error");
- ehi->err_mask |= AC_ERR_DEV;
- } else if (flags & NV_CPB_RESP_CPB_ERR) {
- ata_ehi_push_desc(ehi, ": CPB error");
- ehi->err_mask |= AC_ERR_SYSTEM;
- freeze = 1;
- } else {
- /* notifier error, but no error in CPB flags? */
- ehi->err_mask |= AC_ERR_OTHER;
- freeze = 1;
- }
- /* Kill all commands. EH will determine what actually failed. */
- if (freeze)
- ata_port_freeze(ap);
- else
- ata_port_abort(ap);
- return 1;
- }
- if (flags & NV_CPB_RESP_DONE) {
- struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
- VPRINTK("CPB flags done, flags=0x%x\n", flags);
- if (likely(qc)) {
- /* Grab the ATA port status for non-NCQ commands.
- For NCQ commands the current status may have nothing to do with
- the command just completed. */
- if (qc->tf.protocol != ATA_PROT_NCQ) {
- u8 ata_status = readb(pp->ctl_block + (ATA_REG_STATUS * 4));
- qc->err_mask |= ac_err_mask(ata_status);
- }
- DPRINTK("Completing qc from tag %d with err_mask %u\n",cpb_num,
- qc->err_mask);
- ata_qc_complete(qc);
- }
- }
- return 0;
- }
- static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
- {
- struct ata_queued_cmd *qc = ata_qc_from_tag(ap, ap->active_tag);
- /* freeze if hotplugged */
- if (unlikely(irq_stat & (NV_INT_ADDED | NV_INT_REMOVED))) {
- ata_port_freeze(ap);
- return 1;
- }
- /* bail out if not our interrupt */
- if (!(irq_stat & NV_INT_DEV))
- return 0;
- /* DEV interrupt w/ no active qc? */
- if (unlikely(!qc || (qc->tf.flags & ATA_TFLAG_POLLING))) {
- ata_check_status(ap);
- return 1;
- }
- /* handle interrupt */
- return ata_host_intr(ap, qc);
- }
- static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
- {
- struct ata_host *host = dev_instance;
- int i, handled = 0;
- u32 notifier_clears[2];
- spin_lock(&host->lock);
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
- notifier_clears[i] = 0;
- if (ap && !(ap->flags & ATA_FLAG_DISABLED)) {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- u16 status;
- u32 gen_ctl;
- u32 notifier, notifier_error;
- /* if in ATA register mode, use standard ata interrupt handler */
- if (pp->flags & NV_ADMA_PORT_REGISTER_MODE) {
- u8 irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804)
- >> (NV_INT_PORT_SHIFT * i);
- if(ata_tag_valid(ap->active_tag))
- /** NV_INT_DEV indication seems unreliable at times
- at least in ADMA mode. Force it on always when a
- command is active, to prevent losing interrupts. */
- irq_stat |= NV_INT_DEV;
- handled += nv_host_intr(ap, irq_stat);
- continue;
- }
- notifier = readl(mmio + NV_ADMA_NOTIFIER);
- notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
- notifier_clears[i] = notifier | notifier_error;
- gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
- if( !NV_ADMA_CHECK_INTR(gen_ctl, ap->port_no) && !notifier &&
- !notifier_error)
- /* Nothing to do */
- continue;
- status = readw(mmio + NV_ADMA_STAT);
- /* Clear status. Ensure the controller sees the clearing before we start
- looking at any of the CPB statuses, so that any CPB completions after
- this point in the handler will raise another interrupt. */
- writew(status, mmio + NV_ADMA_STAT);
- readw(mmio + NV_ADMA_STAT); /* flush posted write */
- rmb();
- handled++; /* irq handled if we got here */
- /* freeze if hotplugged or controller error */
- if (unlikely(status & (NV_ADMA_STAT_HOTPLUG |
- NV_ADMA_STAT_HOTUNPLUG |
- NV_ADMA_STAT_TIMEOUT))) {
- struct ata_eh_info *ehi = &ap->eh_info;
- ata_ehi_clear_desc(ehi);
- ata_ehi_push_desc(ehi, "ADMA status 0x%08x", status );
- if (status & NV_ADMA_STAT_TIMEOUT) {
- ehi->err_mask |= AC_ERR_SYSTEM;
- ata_ehi_push_desc(ehi, ": timeout");
- } else if (status & NV_ADMA_STAT_HOTPLUG) {
- ata_ehi_hotplugged(ehi);
- ata_ehi_push_desc(ehi, ": hotplug");
- } else if (status & NV_ADMA_STAT_HOTUNPLUG) {
- ata_ehi_hotplugged(ehi);
- ata_ehi_push_desc(ehi, ": hot unplug");
- }
- ata_port_freeze(ap);
- continue;
- }
- if (status & (NV_ADMA_STAT_DONE |
- NV_ADMA_STAT_CPBERR)) {
- /** Check CPBs for completed commands */
- if (ata_tag_valid(ap->active_tag)) {
- /* Non-NCQ command */
- nv_adma_check_cpb(ap, ap->active_tag,
- notifier_error & (1 << ap->active_tag));
- } else {
- int pos, error = 0;
- u32 active = ap->sactive;
- while ((pos = ffs(active)) && !error) {
- pos--;
- error = nv_adma_check_cpb(ap, pos,
- notifier_error & (1 << pos) );
- active &= ~(1 << pos );
- }
- }
- }
- }
- }
- if(notifier_clears[0] || notifier_clears[1]) {
- /* Note: Both notifier clear registers must be written
- if either is set, even if one is zero, according to NVIDIA. */
- struct nv_adma_port_priv *pp = host->ports[0]->private_data;
- writel(notifier_clears[0], pp->notifier_clear_block);
- pp = host->ports[1]->private_data;
- writel(notifier_clears[1], pp->notifier_clear_block);
- }
- spin_unlock(&host->lock);
- return IRQ_RETVAL(handled);
- }
- static void nv_adma_irq_clear(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- u16 status = readw(mmio + NV_ADMA_STAT);
- u32 notifier = readl(mmio + NV_ADMA_NOTIFIER);
- u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
- void __iomem *dma_stat_addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
- /* clear ADMA status */
- writew(status, mmio + NV_ADMA_STAT);
- writel(notifier | notifier_error,
- pp->notifier_clear_block);
- /** clear legacy status */
- iowrite8(ioread8(dma_stat_addr), dma_stat_addr);
- }
- static void nv_adma_bmdma_setup(struct ata_queued_cmd *qc)
- {
- struct ata_port *ap = qc->ap;
- unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
- struct nv_adma_port_priv *pp = ap->private_data;
- u8 dmactl;
- if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) {
- WARN_ON(1);
- return;
- }
- /* load PRD table addr. */
- iowrite32(ap->prd_dma, ap->ioaddr.bmdma_addr + ATA_DMA_TABLE_OFS);
- /* specify data direction, triple-check start bit is clear */
- dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
- dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
- if (!rw)
- dmactl |= ATA_DMA_WR;
- iowrite8(dmactl, ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
- /* issue r/w command */
- ata_exec_command(ap, &qc->tf);
- }
- static void nv_adma_bmdma_start(struct ata_queued_cmd *qc)
- {
- struct ata_port *ap = qc->ap;
- struct nv_adma_port_priv *pp = ap->private_data;
- u8 dmactl;
- if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) {
- WARN_ON(1);
- return;
- }
- /* start host DMA transaction */
- dmactl = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
- iowrite8(dmactl | ATA_DMA_START,
- ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
- }
- static void nv_adma_bmdma_stop(struct ata_queued_cmd *qc)
- {
- struct ata_port *ap = qc->ap;
- struct nv_adma_port_priv *pp = ap->private_data;
- if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE))
- return;
- /* clear start/stop bit */
- iowrite8(ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
- ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
- /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
- ata_altstatus(ap); /* dummy read */
- }
- static u8 nv_adma_bmdma_status(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- WARN_ON(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE));
- return ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
- }
- static int nv_adma_port_start(struct ata_port *ap)
- {
- struct device *dev = ap->host->dev;
- struct nv_adma_port_priv *pp;
- int rc;
- void *mem;
- dma_addr_t mem_dma;
- void __iomem *mmio;
- u16 tmp;
- VPRINTK("ENTER\n");
- rc = ata_port_start(ap);
- if (rc)
- return rc;
- pp = devm_kzalloc(dev, sizeof(*pp), GFP_KERNEL);
- if (!pp)
- return -ENOMEM;
- mmio = ap->host->iomap[NV_MMIO_BAR] + NV_ADMA_PORT +
- ap->port_no * NV_ADMA_PORT_SIZE;
- pp->ctl_block = mmio;
- pp->gen_block = ap->host->iomap[NV_MMIO_BAR] + NV_ADMA_GEN;
- pp->notifier_clear_block = pp->gen_block +
- NV_ADMA_NOTIFIER_CLEAR + (4 * ap->port_no);
- mem = dmam_alloc_coherent(dev, NV_ADMA_PORT_PRIV_DMA_SZ,
- &mem_dma, GFP_KERNEL);
- if (!mem)
- return -ENOMEM;
- memset(mem, 0, NV_ADMA_PORT_PRIV_DMA_SZ);
- /*
- * First item in chunk of DMA memory:
- * 128-byte command parameter block (CPB)
- * one for each command tag
- */
- pp->cpb = mem;
- pp->cpb_dma = mem_dma;
- writel(mem_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW);
- writel((mem_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH);
- mem += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ;
- mem_dma += NV_ADMA_MAX_CPBS * NV_ADMA_CPB_SZ;
- /*
- * Second item: block of ADMA_SGTBL_LEN s/g entries
- */
- pp->aprd = mem;
- pp->aprd_dma = mem_dma;
- ap->private_data = pp;
- /* clear any outstanding interrupt conditions */
- writew(0xffff, mmio + NV_ADMA_STAT);
- /* initialize port variables */
- pp->flags = NV_ADMA_PORT_REGISTER_MODE;
- /* clear CPB fetch count */
- writew(0, mmio + NV_ADMA_CPB_COUNT);
- /* clear GO for register mode, enable interrupt */
- tmp = readw(mmio + NV_ADMA_CTL);
- writew( (tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL);
- tmp = readw(mmio + NV_ADMA_CTL);
- writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readl( mmio + NV_ADMA_CTL ); /* flush posted write */
- udelay(1);
- writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readl( mmio + NV_ADMA_CTL ); /* flush posted write */
- return 0;
- }
- static void nv_adma_port_stop(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- VPRINTK("ENTER\n");
- writew(0, mmio + NV_ADMA_CTL);
- }
- static int nv_adma_port_suspend(struct ata_port *ap, pm_message_t mesg)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- /* Go to register mode - clears GO */
- nv_adma_register_mode(ap);
- /* clear CPB fetch count */
- writew(0, mmio + NV_ADMA_CPB_COUNT);
- /* disable interrupt, shut down port */
- writew(0, mmio + NV_ADMA_CTL);
- return 0;
- }
- static int nv_adma_port_resume(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- u16 tmp;
- /* set CPB block location */
- writel(pp->cpb_dma & 0xFFFFFFFF, mmio + NV_ADMA_CPB_BASE_LOW);
- writel((pp->cpb_dma >> 16 ) >> 16, mmio + NV_ADMA_CPB_BASE_HIGH);
- /* clear any outstanding interrupt conditions */
- writew(0xffff, mmio + NV_ADMA_STAT);
- /* initialize port variables */
- pp->flags |= NV_ADMA_PORT_REGISTER_MODE;
- /* clear CPB fetch count */
- writew(0, mmio + NV_ADMA_CPB_COUNT);
- /* clear GO for register mode, enable interrupt */
- tmp = readw(mmio + NV_ADMA_CTL);
- writew((tmp & ~NV_ADMA_CTL_GO) | NV_ADMA_CTL_AIEN, mmio + NV_ADMA_CTL);
- tmp = readw(mmio + NV_ADMA_CTL);
- writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readl( mmio + NV_ADMA_CTL ); /* flush posted write */
- udelay(1);
- writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readl( mmio + NV_ADMA_CTL ); /* flush posted write */
- return 0;
- }
- static void nv_adma_setup_port(struct ata_probe_ent *probe_ent, unsigned int port)
- {
- void __iomem *mmio = probe_ent->iomap[NV_MMIO_BAR];
- struct ata_ioports *ioport = &probe_ent->port[port];
- VPRINTK("ENTER\n");
- mmio += NV_ADMA_PORT + port * NV_ADMA_PORT_SIZE;
- ioport->cmd_addr = mmio;
- ioport->data_addr = mmio + (ATA_REG_DATA * 4);
- ioport->error_addr =
- ioport->feature_addr = mmio + (ATA_REG_ERR * 4);
- ioport->nsect_addr = mmio + (ATA_REG_NSECT * 4);
- ioport->lbal_addr = mmio + (ATA_REG_LBAL * 4);
- ioport->lbam_addr = mmio + (ATA_REG_LBAM * 4);
- ioport->lbah_addr = mmio + (ATA_REG_LBAH * 4);
- ioport->device_addr = mmio + (ATA_REG_DEVICE * 4);
- ioport->status_addr =
- ioport->command_addr = mmio + (ATA_REG_STATUS * 4);
- ioport->altstatus_addr =
- ioport->ctl_addr = mmio + 0x20;
- }
- static int nv_adma_host_init(struct ata_probe_ent *probe_ent)
- {
- struct pci_dev *pdev = to_pci_dev(probe_ent->dev);
- unsigned int i;
- u32 tmp32;
- VPRINTK("ENTER\n");
- /* enable ADMA on the ports */
- pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);
- tmp32 |= NV_MCP_SATA_CFG_20_PORT0_EN |
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN |
- NV_MCP_SATA_CFG_20_PORT1_EN |
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN;
- pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
- for (i = 0; i < probe_ent->n_ports; i++)
- nv_adma_setup_port(probe_ent, i);
- return 0;
- }
- static void nv_adma_fill_aprd(struct ata_queued_cmd *qc,
- struct scatterlist *sg,
- int idx,
- struct nv_adma_prd *aprd)
- {
- u8 flags;
- memset(aprd, 0, sizeof(struct nv_adma_prd));
- flags = 0;
- if (qc->tf.flags & ATA_TFLAG_WRITE)
- flags |= NV_APRD_WRITE;
- if (idx == qc->n_elem - 1)
- flags |= NV_APRD_END;
- else if (idx != 4)
- flags |= NV_APRD_CONT;
- aprd->addr = cpu_to_le64(((u64)sg_dma_address(sg)));
- aprd->len = cpu_to_le32(((u32)sg_dma_len(sg))); /* len in bytes */
- aprd->flags = flags;
- }
- static void nv_adma_fill_sg(struct ata_queued_cmd *qc, struct nv_adma_cpb *cpb)
- {
- struct nv_adma_port_priv *pp = qc->ap->private_data;
- unsigned int idx;
- struct nv_adma_prd *aprd;
- struct scatterlist *sg;
- VPRINTK("ENTER\n");
- idx = 0;
- ata_for_each_sg(sg, qc) {
- aprd = (idx < 5) ? &cpb->aprd[idx] : &pp->aprd[NV_ADMA_SGTBL_LEN * qc->tag + (idx-5)];
- nv_adma_fill_aprd(qc, sg, idx, aprd);
- idx++;
- }
- if (idx > 5)
- cpb->next_aprd = cpu_to_le64(((u64)(pp->aprd_dma + NV_ADMA_SGTBL_SZ * qc->tag)));
- }
- static int nv_adma_use_reg_mode(struct ata_queued_cmd *qc)
- {
- struct nv_adma_port_priv *pp = qc->ap->private_data;
- /* ADMA engine can only be used for non-ATAPI DMA commands,
- or interrupt-driven no-data commands. */
- if((pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE) ||
- (qc->tf.flags & ATA_TFLAG_POLLING))
- return 1;
- if((qc->flags & ATA_QCFLAG_DMAMAP) ||
- (qc->tf.protocol == ATA_PROT_NODATA))
- return 0;
- return 1;
- }
- static void nv_adma_qc_prep(struct ata_queued_cmd *qc)
- {
- struct nv_adma_port_priv *pp = qc->ap->private_data;
- struct nv_adma_cpb *cpb = &pp->cpb[qc->tag];
- u8 ctl_flags = NV_CPB_CTL_CPB_VALID |
- NV_CPB_CTL_IEN;
- if (nv_adma_use_reg_mode(qc)) {
- nv_adma_register_mode(qc->ap);
- ata_qc_prep(qc);
- return;
- }
- memset(cpb, 0, sizeof(struct nv_adma_cpb));
- cpb->len = 3;
- cpb->tag = qc->tag;
- cpb->next_cpb_idx = 0;
- /* turn on NCQ flags for NCQ commands */
- if (qc->tf.protocol == ATA_PROT_NCQ)
- ctl_flags |= NV_CPB_CTL_QUEUE | NV_CPB_CTL_FPDMA;
- VPRINTK("qc->flags = 0x%lx\n", qc->flags);
- nv_adma_tf_to_cpb(&qc->tf, cpb->tf);
- if(qc->flags & ATA_QCFLAG_DMAMAP) {
- nv_adma_fill_sg(qc, cpb);
- ctl_flags |= NV_CPB_CTL_APRD_VALID;
- } else
- memset(&cpb->aprd[0], 0, sizeof(struct nv_adma_prd) * 5);
- /* Be paranoid and don't let the device see NV_CPB_CTL_CPB_VALID until we are
- finished filling in all of the contents */
- wmb();
- cpb->ctl_flags = ctl_flags;
- }
- static unsigned int nv_adma_qc_issue(struct ata_queued_cmd *qc)
- {
- struct nv_adma_port_priv *pp = qc->ap->private_data;
- void __iomem *mmio = pp->ctl_block;
- VPRINTK("ENTER\n");
- if (nv_adma_use_reg_mode(qc)) {
- /* use ATA register mode */
- VPRINTK("using ATA register mode: 0x%lx\n", qc->flags);
- nv_adma_register_mode(qc->ap);
- return ata_qc_issue_prot(qc);
- } else
- nv_adma_mode(qc->ap);
- /* write append register, command tag in lower 8 bits
- and (number of cpbs to append -1) in top 8 bits */
- wmb();
- writew(qc->tag, mmio + NV_ADMA_APPEND);
- DPRINTK("Issued tag %u\n",qc->tag);
- return 0;
- }
- static irqreturn_t nv_generic_interrupt(int irq, void *dev_instance)
- {
- struct ata_host *host = dev_instance;
- unsigned int i;
- unsigned int handled = 0;
- unsigned long flags;
- spin_lock_irqsave(&host->lock, flags);
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap;
- ap = host->ports[i];
- if (ap &&
- !(ap->flags & ATA_FLAG_DISABLED)) {
- struct ata_queued_cmd *qc;
- qc = ata_qc_from_tag(ap, ap->active_tag);
- if (qc && (!(qc->tf.flags & ATA_TFLAG_POLLING)))
- handled += ata_host_intr(ap, qc);
- else
- // No request pending? Clear interrupt status
- // anyway, in case there's one pending.
- ap->ops->check_status(ap);
- }
- }
- spin_unlock_irqrestore(&host->lock, flags);
- return IRQ_RETVAL(handled);
- }
- static irqreturn_t nv_do_interrupt(struct ata_host *host, u8 irq_stat)
- {
- int i, handled = 0;
- for (i = 0; i < host->n_ports; i++) {
- struct ata_port *ap = host->ports[i];
- if (ap && !(ap->flags & ATA_FLAG_DISABLED))
- handled += nv_host_intr(ap, irq_stat);
- irq_stat >>= NV_INT_PORT_SHIFT;
- }
- return IRQ_RETVAL(handled);
- }
- static irqreturn_t nv_nf2_interrupt(int irq, void *dev_instance)
- {
- struct ata_host *host = dev_instance;
- u8 irq_stat;
- irqreturn_t ret;
- spin_lock(&host->lock);
- irq_stat = ioread8(host->ports[0]->ioaddr.scr_addr + NV_INT_STATUS);
- ret = nv_do_interrupt(host, irq_stat);
- spin_unlock(&host->lock);
- return ret;
- }
- static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance)
- {
- struct ata_host *host = dev_instance;
- u8 irq_stat;
- irqreturn_t ret;
- spin_lock(&host->lock);
- irq_stat = readb(host->iomap[NV_MMIO_BAR] + NV_INT_STATUS_CK804);
- ret = nv_do_interrupt(host, irq_stat);
- spin_unlock(&host->lock);
- return ret;
- }
- static u32 nv_scr_read (struct ata_port *ap, unsigned int sc_reg)
- {
- if (sc_reg > SCR_CONTROL)
- return 0xffffffffU;
- return ioread32(ap->ioaddr.scr_addr + (sc_reg * 4));
- }
- static void nv_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val)
- {
- if (sc_reg > SCR_CONTROL)
- return;
- iowrite32(val, ap->ioaddr.scr_addr + (sc_reg * 4));
- }
- static void nv_nf2_freeze(struct ata_port *ap)
- {
- void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
- int shift = ap->port_no * NV_INT_PORT_SHIFT;
- u8 mask;
- mask = ioread8(scr_addr + NV_INT_ENABLE);
- mask &= ~(NV_INT_ALL << shift);
- iowrite8(mask, scr_addr + NV_INT_ENABLE);
- }
- static void nv_nf2_thaw(struct ata_port *ap)
- {
- void __iomem *scr_addr = ap->host->ports[0]->ioaddr.scr_addr;
- int shift = ap->port_no * NV_INT_PORT_SHIFT;
- u8 mask;
- iowrite8(NV_INT_ALL << shift, scr_addr + NV_INT_STATUS);
- mask = ioread8(scr_addr + NV_INT_ENABLE);
- mask |= (NV_INT_MASK << shift);
- iowrite8(mask, scr_addr + NV_INT_ENABLE);
- }
- static void nv_ck804_freeze(struct ata_port *ap)
- {
- void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
- int shift = ap->port_no * NV_INT_PORT_SHIFT;
- u8 mask;
- mask = readb(mmio_base + NV_INT_ENABLE_CK804);
- mask &= ~(NV_INT_ALL << shift);
- writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
- }
- static void nv_ck804_thaw(struct ata_port *ap)
- {
- void __iomem *mmio_base = ap->host->iomap[NV_MMIO_BAR];
- int shift = ap->port_no * NV_INT_PORT_SHIFT;
- u8 mask;
- writeb(NV_INT_ALL << shift, mmio_base + NV_INT_STATUS_CK804);
- mask = readb(mmio_base + NV_INT_ENABLE_CK804);
- mask |= (NV_INT_MASK << shift);
- writeb(mask, mmio_base + NV_INT_ENABLE_CK804);
- }
- static int nv_hardreset(struct ata_port *ap, unsigned int *class)
- {
- unsigned int dummy;
- /* SATA hardreset fails to retrieve proper device signature on
- * some controllers. Don't classify on hardreset. For more
- * info, see http://bugme.osdl.org/show_bug.cgi?id=3352
- */
- return sata_std_hardreset(ap, &dummy);
- }
- static void nv_error_handler(struct ata_port *ap)
- {
- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
- nv_hardreset, ata_std_postreset);
- }
- static void nv_adma_error_handler(struct ata_port *ap)
- {
- struct nv_adma_port_priv *pp = ap->private_data;
- if(!(pp->flags & NV_ADMA_PORT_REGISTER_MODE)) {
- void __iomem *mmio = pp->ctl_block;
- int i;
- u16 tmp;
- /* Push us back into port register mode for error handling. */
- nv_adma_register_mode(ap);
- /* Mark all of the CPBs as invalid to prevent them from being executed */
- for( i=0;i<NV_ADMA_MAX_CPBS;i++)
- pp->cpb[i].ctl_flags &= ~NV_CPB_CTL_CPB_VALID;
- /* clear CPB fetch count */
- writew(0, mmio + NV_ADMA_CPB_COUNT);
- /* Reset channel */
- tmp = readw(mmio + NV_ADMA_CTL);
- writew(tmp | NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readl( mmio + NV_ADMA_CTL ); /* flush posted write */
- udelay(1);
- writew(tmp & ~NV_ADMA_CTL_CHANNEL_RESET, mmio + NV_ADMA_CTL);
- readl( mmio + NV_ADMA_CTL ); /* flush posted write */
- }
- ata_bmdma_drive_eh(ap, ata_std_prereset, ata_std_softreset,
- nv_hardreset, ata_std_postreset);
- }
- static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
- {
- static int printed_version = 0;
- struct ata_port_info *ppi[2];
- struct ata_probe_ent *probe_ent;
- struct nv_host_priv *hpriv;
- int rc;
- u32 bar;
- void __iomem *base;
- unsigned long type = ent->driver_data;
- int mask_set = 0;
- // Make sure this is a SATA controller by counting the number of bars
- // (NVIDIA SATA controllers will always have six bars). Otherwise,
- // it's an IDE controller and we ignore it.
- for (bar=0; bar<6; bar++)
- if (pci_resource_start(pdev, bar) == 0)
- return -ENODEV;
- if (!printed_version++)
- dev_printk(KERN_DEBUG, &pdev->dev, "version " DRV_VERSION "\n");
- rc = pcim_enable_device(pdev);
- if (rc)
- return rc;
- rc = pci_request_regions(pdev, DRV_NAME);
- if (rc) {
- pcim_pin_device(pdev);
- return rc;
- }
- if(type >= CK804 && adma_enabled) {
- dev_printk(KERN_NOTICE, &pdev->dev, "Using ADMA mode\n");
- type = ADMA;
- if(!pci_set_dma_mask(pdev, DMA_64BIT_MASK) &&
- !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
- mask_set = 1;
- }
- if(!mask_set) {
- rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
- if (rc)
- return rc;
- rc = pci_set_consistent_dma_mask(pdev, ATA_DMA_MASK);
- if (rc)
- return rc;
- }
- rc = -ENOMEM;
- hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL);
- if (!hpriv)
- return -ENOMEM;
- ppi[0] = ppi[1] = &nv_port_info[type];
- probe_ent = ata_pci_init_native_mode(pdev, ppi, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
- if (!probe_ent)
- return -ENOMEM;
- if (!pcim_iomap(pdev, NV_MMIO_BAR, 0))
- return -EIO;
- probe_ent->iomap = pcim_iomap_table(pdev);
- probe_ent->private_data = hpriv;
- hpriv->type = type;
- base = probe_ent->iomap[NV_MMIO_BAR];
- probe_ent->port[0].scr_addr = base + NV_PORT0_SCR_REG_OFFSET;
- probe_ent->port[1].scr_addr = base + NV_PORT1_SCR_REG_OFFSET;
- /* enable SATA space for CK804 */
- if (type >= CK804) {
- u8 regval;
- pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val);
- regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
- pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
- }
- pci_set_master(pdev);
- if (type == ADMA) {
- rc = nv_adma_host_init(probe_ent);
- if (rc)
- return rc;
- }
- rc = ata_device_add(probe_ent);
- if (rc != NV_PORTS)
- return -ENODEV;
- devm_kfree(&pdev->dev, probe_ent);
- return 0;
- }
- static void nv_remove_one (struct pci_dev *pdev)
- {
- struct ata_host *host = dev_get_drvdata(&pdev->dev);
- struct nv_host_priv *hpriv = host->private_data;
- ata_pci_remove_one(pdev);
- kfree(hpriv);
- }
- static int nv_pci_device_resume(struct pci_dev *pdev)
- {
- struct ata_host *host = dev_get_drvdata(&pdev->dev);
- struct nv_host_priv *hpriv = host->private_data;
- int rc;
- rc = ata_pci_device_do_resume(pdev);
- if(rc)
- return rc;
- if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) {
- if(hpriv->type >= CK804) {
- u8 regval;
- pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val);
- regval |= NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
- pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
- }
- if(hpriv->type == ADMA) {
- u32 tmp32;
- struct nv_adma_port_priv *pp;
- /* enable/disable ADMA on the ports appropriately */
- pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);
- pp = host->ports[0]->private_data;
- if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
- tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN |
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
- else
- tmp32 |= (NV_MCP_SATA_CFG_20_PORT0_EN |
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN);
- pp = host->ports[1]->private_data;
- if(pp->flags & NV_ADMA_ATAPI_SETUP_COMPLETE)
- tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT1_EN |
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
- else
- tmp32 |= (NV_MCP_SATA_CFG_20_PORT1_EN |
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
- pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
- }
- }
- ata_host_resume(host);
- return 0;
- }
- static void nv_ck804_host_stop(struct ata_host *host)
- {
- struct pci_dev *pdev = to_pci_dev(host->dev);
- u8 regval;
- /* disable SATA space for CK804 */
- pci_read_config_byte(pdev, NV_MCP_SATA_CFG_20, ®val);
- regval &= ~NV_MCP_SATA_CFG_20_SATA_SPACE_EN;
- pci_write_config_byte(pdev, NV_MCP_SATA_CFG_20, regval);
- }
- static void nv_adma_host_stop(struct ata_host *host)
- {
- struct pci_dev *pdev = to_pci_dev(host->dev);
- u32 tmp32;
- /* disable ADMA on the ports */
- pci_read_config_dword(pdev, NV_MCP_SATA_CFG_20, &tmp32);
- tmp32 &= ~(NV_MCP_SATA_CFG_20_PORT0_EN |
- NV_MCP_SATA_CFG_20_PORT0_PWB_EN |
- NV_MCP_SATA_CFG_20_PORT1_EN |
- NV_MCP_SATA_CFG_20_PORT1_PWB_EN);
- pci_write_config_dword(pdev, NV_MCP_SATA_CFG_20, tmp32);
- nv_ck804_host_stop(host);
- }
- static int __init nv_init(void)
- {
- return pci_register_driver(&nv_pci_driver);
- }
- static void __exit nv_exit(void)
- {
- pci_unregister_driver(&nv_pci_driver);
- }
- module_init(nv_init);
- module_exit(nv_exit);
- module_param_named(adma, adma_enabled, bool, 0444);
- MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)");
|