mv_sas.c revision 8f261aaf9be5c1246013cf6a65b98586d24832a5
1b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik/* 2b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvsas.c - Marvell 88SE6440 SAS/SATA support 3b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 4b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik Copyright 2007 Red Hat, Inc. 58f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei Copyright 2008 Marvell. <kewei@marvell.com> 6b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 7b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik This program is free software; you can redistribute it and/or 8b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik modify it under the terms of the GNU General Public License as 9b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik published by the Free Software Foundation; either version 2, 10b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik or (at your option) any later version. 11b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 12b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik This program is distributed in the hope that it will be useful, 13b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik but WITHOUT ANY WARRANTY; without even the implied warranty 14b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik See the GNU General Public License for more details. 16b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 17b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik You should have received a copy of the GNU General Public 18b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik License along with this program; see the file COPYING. If not, 19b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik write to the Free Software Foundation, 675 Mass Ave, Cambridge, 20b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MA 02139, USA. 21b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 22b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik --------------------------------------------------------------- 23b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 24b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik Random notes: 25b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * hardware supports controlling the endian-ness of data 26b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik structures. this permits elimination of all the le32_to_cpu() 27b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik and cpu_to_le32() conversions. 28b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 29b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 30b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 31b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik#include <linux/kernel.h> 32b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik#include <linux/module.h> 33b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik#include <linux/pci.h> 34b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik#include <linux/interrupt.h> 35b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik#include <linux/spinlock.h> 36b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik#include <linux/delay.h> 37b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik#include <linux/dma-mapping.h> 38b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik#include <scsi/libsas.h> 39b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik#include <asm/io.h> 40b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#define DRV_NAME "mvsas" 428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#define DRV_VERSION "0.5" 438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#define _MV_DUMP 0 448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#define MVS_DISABLE_NVRAM 458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#define MVS_DISABLE_MSI 46b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 47b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik#define mr32(reg) readl(regs + MVS_##reg) 48b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik#define mw32(reg,val) writel((val), regs + MVS_##reg) 498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#define mw32_f(reg,val) do { \ 50b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik writel((val), regs + MVS_##reg); \ 51b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik readl(regs + MVS_##reg); \ 52b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } while (0) 53b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#define MVS_ID_NOT_MAPPED 0xff 558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width) 568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei/* offset for D2H FIS in the Received FIS List Structure */ 588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#define SATA_RECEIVED_D2H_FIS(reg_set) \ 598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei ((void *) mvi->rx_fis + 0x400 + 0x100 * reg_set + 0x40) 608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#define SATA_RECEIVED_PIO_FIS(reg_set) \ 618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei ((void *) mvi->rx_fis + 0x400 + 0x100 * reg_set + 0x20) 628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#define UNASSOC_D2H_FIS(id) \ 638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei ((void *) mvi->rx_fis + 0x100 * id) 648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#define for_each_phy(__lseq_mask, __mc, __lseq, __rest) \ 668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei for ((__mc) = (__lseq_mask), (__lseq) = 0; \ 678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (__mc) != 0 && __rest; \ 688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (++__lseq), (__mc) >>= 1) 698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 70b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik/* driver compile-time configuration */ 71b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikenum driver_configuration { 72b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_TX_RING_SZ = 1024, /* TX ring size (12-bit) */ 73b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_RX_RING_SZ = 1024, /* RX ring size (12-bit) */ 74b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* software requires power-of-2 75b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik ring size */ 76b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 77b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_SLOTS = 512, /* command slots */ 78b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_SLOT_BUF_SZ = 8192, /* cmd tbl + IU + status + PRD */ 79b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_SSP_CMD_SZ = 64, /* SSP command table buffer size */ 808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_ATA_CMD_SZ = 96, /* SATA command table buffer size */ 81b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_OAF_SZ = 64, /* Open address frame buffer size */ 82b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 83b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_RX_FIS_COUNT = 17, /* Optional rx'd FISs (max 17) */ 848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_QUEUE_SIZE = 30, /* Support Queue depth */ 86b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 87b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 88b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik/* unchangeable hardware details */ 89b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikenum hardware_details { 90b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_MAX_PHYS = 8, /* max. possible phys */ 91b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_MAX_PORTS = 8, /* max. possible ports */ 92b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_RX_FISL_SZ = 0x400 + (MVS_RX_FIS_COUNT * 0x100), 93b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 94b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 95b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik/* peripheral registers (BAR2) */ 96b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikenum peripheral_registers { 97b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik SPI_CTL = 0x10, /* EEPROM control */ 98b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik SPI_CMD = 0x14, /* EEPROM command */ 99b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik SPI_DATA = 0x18, /* EEPROM data */ 100b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 101b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 102b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikenum peripheral_register_bits { 103b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TWSI_RDY = (1U << 7), /* EEPROM interface ready */ 104b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TWSI_RD = (1U << 4), /* EEPROM read access */ 105b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 106b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik SPI_ADDR_MASK = 0x3ffff, /* bits 17:0 */ 107b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 108b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 109b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik/* enhanced mode registers (BAR4) */ 110b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikenum hw_registers { 111b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_GBL_CTL = 0x04, /* global control */ 112b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_GBL_INT_STAT = 0x08, /* global irq status */ 113b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_GBL_PI = 0x0C, /* ports implemented bitmask */ 1148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_GBL_PORT_TYPE = 0xa0, /* port type */ 115b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 116b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_CTL = 0x100, /* SAS/SATA port configuration */ 117b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_PCS = 0x104, /* SAS/SATA port control/status */ 118b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_CMD_LIST_LO = 0x108, /* cmd list addr */ 119b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_CMD_LIST_HI = 0x10C, 120b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_RX_FIS_LO = 0x110, /* RX FIS list addr */ 121b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_RX_FIS_HI = 0x114, 122b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 123b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_TX_CFG = 0x120, /* TX configuration */ 124b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_TX_LO = 0x124, /* TX (delivery) ring addr */ 125b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_TX_HI = 0x128, 126b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_TX_PROD_IDX = 0x12C, /* TX producer pointer */ 1288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_TX_CONS_IDX = 0x130, /* TX consumer pointer (RO) */ 129b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_RX_CFG = 0x134, /* RX configuration */ 130b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_RX_LO = 0x138, /* RX (completion) ring addr */ 131b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_RX_HI = 0x13C, 1328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_RX_CONS_IDX = 0x140, /* RX consumer pointer (RO) */ 133b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 134b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_INT_COAL = 0x148, /* Int coalescing config */ 135b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_INT_COAL_TMOUT = 0x14C, /* Int coalescing timeout */ 136b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_INT_STAT = 0x150, /* Central int status */ 137b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_INT_MASK = 0x154, /* Central int enable */ 138b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_INT_STAT_SRS = 0x158, /* SATA register set status */ 1398f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_INT_MASK_SRS = 0x15C, 140b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 141b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* ports 1-3 follow after this */ 142b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_P0_INT_STAT = 0x160, /* port0 interrupt status */ 143b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_P0_INT_MASK = 0x164, /* port0 interrupt mask */ 1448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_P4_INT_STAT = 0x200, /* Port 4 interrupt status */ 1458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_P4_INT_MASK = 0x204, /* Port 4 interrupt enable mask */ 146b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 147b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* ports 1-3 follow after this */ 148b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_P0_SER_CTLSTAT = 0x180, /* port0 serial control/status */ 1498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_P4_SER_CTLSTAT = 0x220, /* port4 serial control/status */ 150b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 151b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_CMD_ADDR = 0x1B8, /* Command register port (addr) */ 152b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_CMD_DATA = 0x1BC, /* Command register port (data) */ 153b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 154b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* ports 1-3 follow after this */ 155b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_P0_CFG_ADDR = 0x1C0, /* port0 phy register address */ 156b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVS_P0_CFG_DATA = 0x1C4, /* port0 phy register data */ 1578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_P4_CFG_ADDR = 0x230, /* Port 4 config address */ 1588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_P4_CFG_DATA = 0x234, /* Port 4 config data */ 1598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* ports 1-3 follow after this */ 1618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_P0_VSR_ADDR = 0x1E0, /* port0 VSR address */ 1628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_P0_VSR_DATA = 0x1E4, /* port0 VSR data */ 1638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_P4_VSR_ADDR = 0x250, /* port 4 VSR addr */ 1648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MVS_P4_VSR_DATA = 0x254, /* port 4 VSR data */ 165b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 166b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 167b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikenum hw_register_bits { 168b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* MVS_GBL_CTL */ 169b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik INT_EN = (1U << 1), /* Global int enable */ 170b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik HBA_RST = (1U << 0), /* HBA reset */ 171b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 172b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* MVS_GBL_INT_STAT */ 173b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik INT_XOR = (1U << 4), /* XOR engine event */ 174b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik INT_SAS_SATA = (1U << 0), /* SAS/SATA event */ 175b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 176b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* MVS_GBL_PORT_TYPE */ /* shl for ports 1-3 */ 177b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik SATA_TARGET = (1U << 16), /* port0 SATA target enable */ 1788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_AUTO_DET_PORT7 = (1U << 15), /* port0 SAS/SATA autodetect */ 1798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_AUTO_DET_PORT6 = (1U << 14), 1808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_AUTO_DET_PORT5 = (1U << 13), 1818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_AUTO_DET_PORT4 = (1U << 12), 1828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_AUTO_DET_PORT3 = (1U << 11), 1838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_AUTO_DET_PORT2 = (1U << 10), 1848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_AUTO_DET_PORT1 = (1U << 9), 1858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_AUTO_DET_PORT0 = (1U << 8), 1868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_AUTO_DET_EN = MODE_AUTO_DET_PORT0 | MODE_AUTO_DET_PORT1 | 1878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_AUTO_DET_PORT2 | MODE_AUTO_DET_PORT3 | 1888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_AUTO_DET_PORT4 | MODE_AUTO_DET_PORT5 | 1898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_AUTO_DET_PORT6 | MODE_AUTO_DET_PORT7, 1908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_SAS_PORT7_MASK = (1U << 7), /* port0 SAS(1), SATA(0) mode */ 1918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_SAS_PORT6_MASK = (1U << 6), 1928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_SAS_PORT5_MASK = (1U << 5), 1938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_SAS_PORT4_MASK = (1U << 4), 1948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_SAS_PORT3_MASK = (1U << 3), 1958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_SAS_PORT2_MASK = (1U << 2), 1968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_SAS_PORT1_MASK = (1U << 1), 1978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_SAS_PORT0_MASK = (1U << 0), 1988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_SAS_SATA = MODE_SAS_PORT0_MASK | MODE_SAS_PORT1_MASK | 1998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_SAS_PORT2_MASK | MODE_SAS_PORT3_MASK | 2008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_SAS_PORT4_MASK | MODE_SAS_PORT5_MASK | 2018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei MODE_SAS_PORT6_MASK | MODE_SAS_PORT7_MASK, 2028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 2038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* SAS_MODE value may be 2048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * dictated (in hw) by values 2058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * of SATA_TARGET & AUTO_DET 2068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei */ 207b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 208b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* MVS_TX_CFG */ 209b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TX_EN = (1U << 16), /* Enable TX */ 210b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TX_RING_SZ_MASK = 0xfff, /* TX ring size, bits 11:0 */ 211b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 212b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* MVS_RX_CFG */ 213b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik RX_EN = (1U << 16), /* Enable RX */ 214b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik RX_RING_SZ_MASK = 0xfff, /* RX ring size, bits 11:0 */ 215b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 216b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* MVS_INT_COAL */ 217b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik COAL_EN = (1U << 16), /* Enable int coalescing */ 218b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 219b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* MVS_INT_STAT, MVS_INT_MASK */ 220b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CINT_I2C = (1U << 31), /* I2C event */ 221b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CINT_SW0 = (1U << 30), /* software event 0 */ 222b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CINT_SW1 = (1U << 29), /* software event 1 */ 223b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CINT_PRD_BC = (1U << 28), /* PRD BC err for read cmd */ 224b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CINT_DMA_PCIE = (1U << 27), /* DMA to PCIE timeout */ 225b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CINT_MEM = (1U << 26), /* int mem parity err */ 226b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CINT_I2C_SLAVE = (1U << 25), /* slave I2C event */ 227b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CINT_SRS = (1U << 3), /* SRS event */ 2288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei CINT_CI_STOP = (1U << 1), /* cmd issue stopped */ 229b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CINT_DONE = (1U << 0), /* cmd completion */ 230b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 231b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* shl for ports 1-3 */ 232b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CINT_PORT_STOPPED = (1U << 16), /* port0 stopped */ 233b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CINT_PORT = (1U << 8), /* port0 event */ 2348f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei CINT_PORT_MASK_OFFSET = 8, 2358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei CINT_PORT_MASK = (0xFF << CINT_PORT_MASK_OFFSET), 236b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 237b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* TX (delivery) ring bits */ 238b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TXQ_CMD_SHIFT = 29, 239b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TXQ_CMD_SSP = 1, /* SSP protocol */ 240b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TXQ_CMD_SMP = 2, /* SMP protocol */ 241b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TXQ_CMD_STP = 3, /* STP/SATA protocol */ 242b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TXQ_CMD_SSP_FREE_LIST = 4, /* add to SSP targ free list */ 243b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TXQ_CMD_SLOT_RESET = 7, /* reset command slot */ 244b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TXQ_MODE_I = (1U << 28), /* mode: 0=target,1=initiator */ 245b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TXQ_PRIO_HI = (1U << 27), /* priority: 0=normal, 1=high */ 246b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TXQ_SRS_SHIFT = 20, /* SATA register set */ 247b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TXQ_SRS_MASK = 0x7f, 248b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TXQ_PHY_SHIFT = 12, /* PHY bitmap */ 249b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TXQ_PHY_MASK = 0xff, 250b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik TXQ_SLOT_MASK = 0xfff, /* slot number */ 251b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 252b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* RX (completion) ring bits */ 253b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik RXQ_GOOD = (1U << 23), /* Response good */ 254b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik RXQ_SLOT_RESET = (1U << 21), /* Slot reset complete */ 255b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik RXQ_CMD_RX = (1U << 20), /* target cmd received */ 256b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik RXQ_ATTN = (1U << 19), /* attention */ 257b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik RXQ_RSP = (1U << 18), /* response frame xfer'd */ 258b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik RXQ_ERR = (1U << 17), /* err info rec xfer'd */ 259b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik RXQ_DONE = (1U << 16), /* cmd complete */ 260b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik RXQ_SLOT_MASK = 0xfff, /* slot number */ 261b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 262b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* mvs_cmd_hdr bits */ 263b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_PRD_LEN_SHIFT = 16, /* 16-bit PRD table len */ 264b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_SSP_FR_TYPE_SHIFT = 13, /* SSP frame type */ 265b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 266b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* SSP initiator only */ 267b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_SSP_FR_CMD = 0x0, /* COMMAND frame */ 268b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 269b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* SSP initiator or target */ 270b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_SSP_FR_TASK = 0x1, /* TASK frame */ 271b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 272b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* SSP target only */ 273b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_SSP_FR_XFER_RDY = 0x4, /* XFER_RDY frame */ 274b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_SSP_FR_RESP = 0x5, /* RESPONSE frame */ 275b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_SSP_FR_READ = 0x6, /* Read DATA frame(s) */ 276b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_SSP_FR_READ_RESP = 0x7, /* ditto, plus RESPONSE */ 277b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 278b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_PASSTHRU = (1U << 12), /* pass-through (SSP) */ 279b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_FBURST = (1U << 11), /* first burst (SSP) */ 280b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_CHK_LEN = (1U << 10), /* chk xfer len (SSP) */ 281b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_RETRY = (1U << 9), /* tport layer retry (SSP) */ 282b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_PROTECTION = (1U << 8), /* protection info rec (SSP) */ 283b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_RESET = (1U << 7), /* Reset (STP/SATA) */ 284b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_FPDMA = (1U << 6), /* First party DMA (STP/SATA) */ 285b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_ATAPI = (1U << 5), /* ATAPI (STP/SATA) */ 286b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_BIST = (1U << 4), /* BIST activate (STP/SATA) */ 287b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MCH_PMP_MASK = 0xf, /* PMP from cmd FIS (STP/SATA)*/ 288b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 289b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CCTL_RST = (1U << 5), /* port logic reset */ 290b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 291b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* 0(LSB first), 1(MSB first) */ 292b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CCTL_ENDIAN_DATA = (1U << 3), /* PRD data */ 293b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CCTL_ENDIAN_RSP = (1U << 2), /* response frame */ 294b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CCTL_ENDIAN_OPEN = (1U << 1), /* open address frame */ 295b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CCTL_ENDIAN_CMD = (1U << 0), /* command table */ 296b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 297b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* MVS_Px_SER_CTLSTAT (per-phy control) */ 298b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHY_SSP_RST = (1U << 3), /* reset SSP link layer */ 299b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHY_BCAST_CHG = (1U << 2), /* broadcast(change) notif */ 300b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHY_RST_HARD = (1U << 1), /* hard reset + phy reset */ 301b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHY_RST = (1U << 0), /* phy reset */ 3028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHY_MIN_SPP_PHYS_LINK_RATE_MASK = (0xF << 8), 3038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0xF << 12), 3048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = (16), 3058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHY_NEG_SPP_PHYS_LINK_RATE_MASK = 3068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (0xF << PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET), 3078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHY_READY_MASK = (1U << 20), 308b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 309b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* MVS_Px_INT_STAT, MVS_Px_INT_MASK (per-phy events) */ 3108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHYEV_DEC_ERR = (1U << 24), /* Phy Decoding Error */ 311b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_UNASSOC_FIS = (1U << 19), /* unassociated FIS rx'd */ 312b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_AN = (1U << 18), /* SATA async notification */ 313b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_BIST_ACT = (1U << 17), /* BIST activate FIS */ 314b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_SIG_FIS = (1U << 16), /* signature FIS */ 315b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_POOF = (1U << 12), /* phy ready from 1 -> 0 */ 316b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_IU_BIG = (1U << 11), /* IU too long err */ 317b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_IU_SMALL = (1U << 10), /* IU too short err */ 318b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_UNK_TAG = (1U << 9), /* unknown tag */ 319b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_BROAD_CH = (1U << 8), /* broadcast(CHANGE) */ 320b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_COMWAKE = (1U << 7), /* COMWAKE rx'd */ 321b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_PORT_SEL = (1U << 6), /* port selector present */ 322b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_HARD_RST = (1U << 5), /* hard reset rx'd */ 323b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_ID_TMOUT = (1U << 4), /* identify timeout */ 324b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_ID_FAIL = (1U << 3), /* identify failed */ 325b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_ID_DONE = (1U << 2), /* identify done */ 326b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_HARD_RST_DONE = (1U << 1), /* hard reset done */ 327b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYEV_RDY_CH = (1U << 0), /* phy ready changed state */ 328b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 329b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* MVS_PCS */ 3308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PCS_EN_SATA_REG_SHIFT = (16), /* Enable SATA Register Set */ 3318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PCS_EN_PORT_XMT_SHIFT = (12), /* Enable Port Transmit */ 3328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PCS_EN_PORT_XMT_SHIFT2 = (8), /* For 6480 */ 333b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PCS_SATA_RETRY = (1U << 8), /* retry ctl FIS on R_ERR */ 334b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PCS_RSP_RX_EN = (1U << 7), /* raw response rx */ 335b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PCS_SELF_CLEAR = (1U << 5), /* self-clearing int mode */ 336b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PCS_FIS_RX_EN = (1U << 4), /* FIS rx enable */ 337b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PCS_CMD_STOP_ERR = (1U << 3), /* cmd stop-on-err enable */ 3388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PCS_CMD_RST = (1U << 1), /* reset cmd issue */ 339b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PCS_CMD_EN = (1U << 0), /* enable cmd issue */ 3408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 3418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* Port n Attached Device Info */ 3428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORT_DEV_SSP_TRGT = (1U << 19), 3438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORT_DEV_SMP_TRGT = (1U << 18), 3448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORT_DEV_STP_TRGT = (1U << 17), 3458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORT_DEV_SSP_INIT = (1U << 11), 3468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORT_DEV_SMP_INIT = (1U << 10), 3478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORT_DEV_STP_INIT = (1U << 9), 3488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORT_PHY_ID_MASK = (0xFFU << 24), 3498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORT_DEV_TRGT_MASK = (0x7U << 17), 3508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORT_DEV_INIT_MASK = (0x7U << 9), 3518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORT_DEV_TYPE_MASK = (0x7U << 0), 3528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 3538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* Port n PHY Status */ 3548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHY_RDY = (1U << 2), 3558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHY_DW_SYNC = (1U << 1), 3568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHY_OOB_DTCTD = (1U << 0), 3578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 3588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* VSR */ 3598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* PHYMODE 6 (CDB) */ 3608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHY_MODE6_DTL_SPEED = (1U << 27), 361b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 362b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 363b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikenum mvs_info_flags { 364b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVF_MSI = (1U << 0), /* MSI is enabled */ 365b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik MVF_PHY_PWR_FIX = (1U << 1), /* bug workaround */ 366b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 367b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 368b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikenum sas_cmd_port_registers { 369b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_CMRST_OOB_DET = 0x100, /* COMRESET OOB detect register */ 370b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_CMWK_OOB_DET = 0x104, /* COMWAKE OOB detect register */ 371b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_CMSAS_OOB_DET = 0x108, /* COMSAS OOB detect register */ 372b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_BRST_OOB_DET = 0x10c, /* burst OOB detect register */ 373b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_OOB_SPACE = 0x110, /* OOB space control register */ 374b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_OOB_BURST = 0x114, /* OOB burst control register */ 375b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PHY_TIMER = 0x118, /* PHY timer control register */ 376b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PHY_CONFIG0 = 0x11c, /* PHY config register 0 */ 377b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PHY_CONFIG1 = 0x120, /* PHY config register 1 */ 378b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_SAS_CTL0 = 0x124, /* SAS control register 0 */ 379b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_SAS_CTL1 = 0x128, /* SAS control register 1 */ 380b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_SAS_CTL2 = 0x12c, /* SAS control register 2 */ 381b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_SAS_CTL3 = 0x130, /* SAS control register 3 */ 382b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_ID_TEST = 0x134, /* ID test register */ 383b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PL_TIMER = 0x138, /* PL timer register */ 384b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_WD_TIMER = 0x13c, /* WD timer register */ 385b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PORT_SEL_COUNT = 0x140, /* port selector count register */ 386b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_APP_MEM_CTL = 0x144, /* Application Memory Control */ 387b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_XOR_MEM_CTL = 0x148, /* XOR Block Memory Control */ 388b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_DMA_MEM_CTL = 0x14c, /* DMA Block Memory Control */ 389b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PORT_MEM_CTL0 = 0x150, /* Port Memory Control 0 */ 390b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PORT_MEM_CTL1 = 0x154, /* Port Memory Control 1 */ 391b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_SATA_PORT_MEM_CTL0 = 0x158, /* SATA Port Memory Control 0 */ 392b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_SATA_PORT_MEM_CTL1 = 0x15c, /* SATA Port Memory Control 1 */ 393b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_XOR_MEM_BIST_CTL = 0x160, /* XOR Memory BIST Control */ 394b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_XOR_MEM_BIST_STAT = 0x164, /* XOR Memroy BIST Status */ 395b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_DMA_MEM_BIST_CTL = 0x168, /* DMA Memory BIST Control */ 396b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_DMA_MEM_BIST_STAT = 0x16c, /* DMA Memory BIST Status */ 397b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PORT_MEM_BIST_CTL = 0x170, /* Port Memory BIST Control */ 398b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PORT_MEM_BIST_STAT0 = 0x174, /* Port Memory BIST Status 0 */ 399b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PORT_MEM_BIST_STAT1 = 0x178, /* Port Memory BIST Status 1 */ 400b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_STP_MEM_BIST_CTL = 0x17c, /* STP Memory BIST Control */ 401b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_STP_MEM_BIST_STAT0 = 0x180, /* STP Memory BIST Status 0 */ 402b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_STP_MEM_BIST_STAT1 = 0x184, /* STP Memory BIST Status 1 */ 403b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_RESET_COUNT = 0x188, /* Reset Count */ 404b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_MONTR_DATA_SEL = 0x18C, /* Monitor Data/Select */ 405b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PLL_PHY_CONFIG = 0x190, /* PLL/PHY Configuration */ 406b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PHY_CTL = 0x194, /* PHY Control and Status */ 407b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PHY_TEST_COUNT0 = 0x198, /* Phy Test Count 0 */ 408b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PHY_TEST_COUNT1 = 0x19C, /* Phy Test Count 1 */ 409b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PHY_TEST_COUNT2 = 0x1A0, /* Phy Test Count 2 */ 410b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_APP_ERR_CONFIG = 0x1A4, /* Application Error Configuration */ 411b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PND_FIFO_CTL0 = 0x1A8, /* Pending FIFO Control 0 */ 412b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_HOST_CTL = 0x1AC, /* Host Control Status */ 413b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_HOST_WR_DATA = 0x1B0, /* Host Write Data */ 414b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_HOST_RD_DATA = 0x1B4, /* Host Read Data */ 415b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PHY_MODE_21 = 0x1B8, /* Phy Mode 21 */ 416b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_SL_MODE0 = 0x1BC, /* SL Mode 0 */ 417b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_SL_MODE1 = 0x1C0, /* SL Mode 1 */ 418b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik CMD_PND_FIFO_CTL1 = 0x1C4, /* Pending FIFO Control 1 */ 419b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 420b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 421b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik/* SAS/SATA configuration port registers, aka phy registers */ 422b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikenum sas_sata_config_port_regs { 4238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHYR_IDENTIFY = 0x00, /* info for IDENTIFY frame */ 4248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHYR_ADDR_LO = 0x04, /* my SAS address (low) */ 4258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHYR_ADDR_HI = 0x08, /* my SAS address (high) */ 4268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHYR_ATT_DEV_INFO = 0x0C, /* attached device info */ 427b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYR_ATT_ADDR_LO = 0x10, /* attached dev SAS addr (low) */ 428b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYR_ATT_ADDR_HI = 0x14, /* attached dev SAS addr (high) */ 429b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYR_SATA_CTL = 0x18, /* SATA control */ 430b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYR_PHY_STAT = 0x1C, /* PHY status */ 4318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHYR_SATA_SIG0 = 0x20, /*port SATA signature FIS(Byte 0-3) */ 4328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHYR_SATA_SIG1 = 0x24, /*port SATA signature FIS(Byte 4-7) */ 4338f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHYR_SATA_SIG2 = 0x28, /*port SATA signature FIS(Byte 8-11) */ 4348f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHYR_SATA_SIG3 = 0x2c, /*port SATA signature FIS(Byte 12-15) */ 4358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHYR_R_ERR_COUNT = 0x30, /* port R_ERR count register */ 4368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHYR_CRC_ERR_COUNT = 0x34, /* port CRC error count register */ 437b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYR_WIDE_PORT = 0x38, /* wide port participating */ 438b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYR_CURRENT0 = 0x80, /* current connection info 0 */ 439b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYR_CURRENT1 = 0x84, /* current connection info 1 */ 440b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PHYR_CURRENT2 = 0x88, /* current connection info 2 */ 441b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 442b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 4438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei/* SAS/SATA Vendor Specific Port Registers */ 4448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weienum sas_sata_vsp_regs { 4458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_STAT = 0x00, /* Phy Status */ 4468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_MODE1 = 0x01, /* phy tx */ 4478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_MODE2 = 0x02, /* tx scc */ 4488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_MODE3 = 0x03, /* pll */ 4498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_MODE4 = 0x04, /* VCO */ 4508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_MODE5 = 0x05, /* Rx */ 4518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_MODE6 = 0x06, /* CDR */ 4528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_MODE7 = 0x07, /* Impedance */ 4538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_MODE8 = 0x08, /* Voltage */ 4548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_MODE9 = 0x09, /* Test */ 4558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_MODE10 = 0x0A, /* Power */ 4568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_MODE11 = 0x0B, /* Phy Mode */ 4578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_VS0 = 0x0C, /* Vednor Specific 0 */ 4588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei VSR_PHY_VS1 = 0x0D, /* Vednor Specific 1 */ 4598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei}; 4608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 461b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikenum pci_cfg_registers { 4628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PCR_PHY_CTL = 0x40, 4638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PCR_PHY_CTL2 = 0x90, 4648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PCR_DEV_CTRL = 0xE8, 465b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 466b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 467b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikenum pci_cfg_register_bits { 4688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PCTL_PWR_ON = (0xFU << 24), 4698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PCTL_OFF = (0xFU << 12), 4708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PRD_REQ_SIZE = (0x4000), 4718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PRD_REQ_MASK = (0x00007000), 472b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 473b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 474b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikenum nvram_layout_offsets { 4758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei NVR_SIG = 0x00, /* 0xAA, 0x55 */ 4768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei NVR_SAS_ADDR = 0x02, /* 8-byte SAS address */ 477b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 478b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 479b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikenum chip_flavors { 480b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik chip_6320, 481b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik chip_6440, 482b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik chip_6480, 483b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 484b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 4858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weienum port_type { 4868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORT_TYPE_SAS = (1L << 1), 4878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORT_TYPE_SATA = (1L << 0), 4888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei}; 4898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 4908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei/* Command Table Format */ 4918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weienum ct_format { 4928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* SSP */ 4938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei SSP_F_H = 0x00, 4948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei SSP_F_IU = 0x18, 4958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei SSP_F_MAX = 0x4D, 4968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* STP */ 4978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei STP_CMD_FIS = 0x00, 4988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei STP_ATAPI_CMD = 0x40, 4998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei STP_F_MAX = 0x10, 5008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* SMP */ 5018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei SMP_F_T = 0x00, 5028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei SMP_F_DEP = 0x01, 5038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei SMP_F_MAX = 0x101, 5048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei}; 5058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 5068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weienum status_buffer { 5078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei SB_EIR_OFF = 0x00, /* Error Information Record */ 5088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei SB_RFB_OFF = 0x08, /* Response Frame Buffer */ 5098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei SB_RFB_MAX = 0x400, /* RFB size*/ 5108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei}; 5118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 5128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weienum error_info_rec { 5138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei CMD_ISS_STPD = (1U << 31), /* Cmd Issue Stopped */ 5148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei}; 5158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 516b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstruct mvs_chip_info { 5178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 n_phy; 5188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 srs_sz; 5198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 slot_width; 520b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 521b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 522b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstruct mvs_err_info { 523b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le32 flags; 524b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le32 flags2; 525b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 526b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 527b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstruct mvs_prd { 528b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le64 addr; /* 64-bit buffer address */ 529b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le32 reserved; 530b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le32 len; /* 16-bit length */ 531b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 532b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 533b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstruct mvs_cmd_hdr { 534b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le32 flags; /* PRD tbl len; SAS, SATA ctl */ 535b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le32 lens; /* cmd, max resp frame len */ 536b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le32 tags; /* targ port xfer tag; tag */ 537b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le32 data_len; /* data xfer len */ 538b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le64 cmd_tbl; /* command table address */ 539b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le64 open_frame; /* open addr frame address */ 540b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le64 status_buf; /* status buffer address */ 541b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le64 prd_tbl; /* PRD tbl address */ 542b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le32 reserved[4]; 543b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 544b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 545b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstruct mvs_slot_info { 546b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct sas_task *task; 5478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 n_elem; 5488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tx; 549b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 550b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* DMA buffer for storing cmd tbl, open addr frame, status buffer, 551b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * and PRD table 552b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 553b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void *buf; 554b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_addr_t buf_dma; 5558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#if _MV_DUMP 5568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 cmd_size; 5578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 558b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 559b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void *response; 560b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 561b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 562b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstruct mvs_port { 563b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct asd_sas_port sas_port; 5648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u8 port_attached; 5658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u8 taskfileset; 5668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u8 wide_port_phymap; 567b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 568b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 569b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstruct mvs_phy { 570b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_port *port; 571b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct asd_sas_phy sas_phy; 5728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct sas_identify identify; 5738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct scsi_device *sdev; 5748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u64 dev_sas_addr; 5758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u64 att_dev_sas_addr; 5768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 att_dev_info; 5778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 dev_info; 5788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 phy_type; 5798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 phy_status; 5808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 irq_status; 5818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 frame_rcvd_size; 5828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u8 frame_rcvd[32]; 5838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u8 phy_attached; 584b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 585b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 586b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstruct mvs_info { 587b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik unsigned long flags; 588b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 589b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik spinlock_t lock; /* host-wide lock */ 590b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct pci_dev *pdev; /* our device */ 591b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void __iomem *regs; /* enhanced mode registers */ 592b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void __iomem *peri_regs; /* peripheral registers */ 593b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 594b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u8 sas_addr[SAS_ADDR_SIZE]; 595b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct sas_ha_struct sas; /* SCSI/SAS glue */ 596b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct Scsi_Host *shost; 597b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 598b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le32 *tx; /* TX (delivery) DMA ring */ 599b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_addr_t tx_dma; 600b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u32 tx_prod; /* cached next-producer idx */ 601b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 602b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le32 *rx; /* RX (completion) DMA ring */ 603b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_addr_t rx_dma; 604b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u32 rx_cons; /* RX consumer idx */ 605b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 606b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik __le32 *rx_fis; /* RX'd FIS area */ 607b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_addr_t rx_fis_dma; 608b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 6098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_cmd_hdr *slot; /* DMA command header slots */ 610b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_addr_t slot_dma; 611b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 612b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik const struct mvs_chip_info *chip; 613b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 6148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei unsigned long tags[MVS_SLOTS]; 615b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_slot_info slot_info[MVS_SLOTS]; 6168f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* further per-slot information */ 617b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_phy phy[MVS_MAX_PHYS]; 618b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_port port[MVS_MAX_PHYS]; 6198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 6208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 can_queue; /* per adapter */ 6218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tag_out; /*Get*/ 6228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tag_in; /*Give*/ 623b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 624b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 6258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistruct mvs_queue_task { 6268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct list_head list; 6278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 6288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void *uldd_task; 6298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei}; 6308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 6318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, 6328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void *funcdata); 6338f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_read_phy_ctl(struct mvs_info *mvi, u32 port); 6348f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_phy_ctl(struct mvs_info *mvi, u32 port, u32 val); 6358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_read_port(struct mvs_info *mvi, u32 off, u32 off2, u32 port); 6368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port(struct mvs_info *mvi, u32 off, u32 off2, 6378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 port, u32 val); 6388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_read_port_cfg_data(struct mvs_info *mvi, u32 port); 6398f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port_cfg_data(struct mvs_info *mvi, u32 port, u32 val); 6408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port_cfg_addr(struct mvs_info *mvi, u32 port, u32 addr); 6418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_read_port_vsr_data(struct mvs_info *mvi, u32 port); 6428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port_vsr_data(struct mvs_info *mvi, u32 port, u32 val); 6438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port_vsr_addr(struct mvs_info *mvi, u32 port, u32 addr); 6448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_read_port_irq_stat(struct mvs_info *mvi, u32 port); 6458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port_irq_stat(struct mvs_info *mvi, u32 port, u32 val); 6468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port_irq_mask(struct mvs_info *mvi, u32 port, u32 val); 6478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_read_port_irq_mask(struct mvs_info *mvi, u32 port); 6488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 6498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_is_phy_ready(struct mvs_info *mvi, int i); 6508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_detect_porttype(struct mvs_info *mvi, int i); 6518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st); 6528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_free_reg_set(struct mvs_info *mvi, struct mvs_port *port); 6538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u8 mvs_assign_reg_set(struct mvs_info *mvi, struct mvs_port *port); 6548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_is_sig_fis_received(u32 irq_status); 6558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 6568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_scan_finished(struct Scsi_Host *, unsigned long); 6578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_scan_start(struct Scsi_Host *); 6588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_sas_slave_alloc(struct scsi_device *scsi_dev); 6598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 660b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic struct scsi_transport_template *mvs_stt; 661b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 662b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic const struct mvs_chip_info mvs_chips[] = { 6638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei [chip_6320] = { 2, 16, 9 }, 6648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei [chip_6440] = { 4, 16, 9 }, 665b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik [chip_6480] = { 8, 32, 10 }, 666b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 667b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 668b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic struct scsi_host_template mvs_sht = { 669b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .module = THIS_MODULE, 670b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .name = DRV_NAME, 671b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .queuecommand = sas_queuecommand, 672b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .target_alloc = sas_target_alloc, 673b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .slave_configure = sas_slave_configure, 674b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .slave_destroy = sas_slave_destroy, 6758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei .scan_finished = mvs_scan_finished, 6768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei .scan_start = mvs_scan_start, 677b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .change_queue_depth = sas_change_queue_depth, 678b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .change_queue_type = sas_change_queue_type, 679b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .bios_param = sas_bios_param, 680b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .can_queue = 1, 681b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .cmd_per_lun = 1, 682b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .this_id = -1, 683b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .sg_tablesize = SG_ALL, 684b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .max_sectors = SCSI_DEFAULT_MAX_SECTORS, 685b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .use_clustering = ENABLE_CLUSTERING, 6868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei .eh_device_reset_handler = sas_eh_device_reset_handler, 687b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .eh_bus_reset_handler = sas_eh_bus_reset_handler, 6888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei .slave_alloc = mvs_sas_slave_alloc, 689b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .target_destroy = sas_target_destroy, 690b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .ioctl = sas_ioctl, 691b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 692b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 6938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_hexdump(u32 size, u8 *data, u32 baseaddr) 6948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 6958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 i; 6968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 run; 6978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 offset; 6988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 6998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei offset = 0; 7008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei while (size) { 7018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei printk("%08X : ", baseaddr + offset); 7028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (size >= 16) 7038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei run = 16; 7048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 7058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei run = size; 7068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei size -= run; 7078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei for (i = 0; i < 16; i++) { 7088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (i < run) 7098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei printk("%02X ", (u32)data[i]); 7108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 7118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei printk(" "); 7128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 7138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei printk(": "); 7148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei for (i = 0; i < run; i++) 7158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei printk("%c", isalnum(data[i]) ? data[i] : '.'); 7168f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei printk("\n"); 7178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei data = &data[16]; 7188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei offset += run; 7198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 7208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei printk("\n"); 7218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 7228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 7238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_hba_sb_dump(struct mvs_info *mvi, u32 tag, 7248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei enum sas_protocol proto) 7258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 7268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#if _MV_DUMP 7278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 offset; 7288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct pci_dev *pdev = mvi->pdev; 7298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_slot_info *slot = &mvi->slot_info[tag]; 7308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 7318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei offset = slot->cmd_size + MVS_OAF_SZ + 7328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sizeof(struct mvs_prd) * slot->n_elem; 7338f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, "+---->Status buffer[%d] :\n", 7348f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tag); 7358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(32, (u8 *) slot->response, 7368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u32) slot->buf_dma + offset); 7378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 7388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 7398f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 7408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag, 7418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei enum sas_protocol proto) 7428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 7438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#if _MV_DUMP 7448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 sz, w_ptr, r_ptr; 7458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u64 addr; 7468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs; 7478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct pci_dev *pdev = mvi->pdev; 7488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_slot_info *slot = &mvi->slot_info[tag]; 7498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 7508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*Delivery Queue */ 7518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sz = mr32(TX_CFG) & TX_RING_SZ_MASK; 7528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei w_ptr = mr32(TX_PROD_IDX) & TX_RING_SZ_MASK; 7538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei r_ptr = mr32(TX_CONS_IDX) & TX_RING_SZ_MASK; 7548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei addr = mr32(TX_HI) << 16 << 16 | mr32(TX_LO); 7558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, 7568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "Delivery Queue Size=%04d , WRT_PTR=%04X , RD_PTR=%04X\n", 7578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sz, w_ptr, r_ptr); 7588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, 7598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "Delivery Queue Base Address=0x%llX (PA)" 7608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "(tx_dma=0x%llX), Entry=%04d\n", 7618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei addr, mvi->tx_dma, w_ptr); 7628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(sizeof(u32), (u8 *)(&mvi->tx[mvi->tx_prod]), 7638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u32) mvi->tx_dma + sizeof(u32) * w_ptr); 7648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*Command List */ 7658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei addr = mr32(CMD_LIST_HI) << 16 << 16 | mr32(CMD_LIST_LO); 7668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, 7678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "Command List Base Address=0x%llX (PA)" 7688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "(slot_dma=0x%llX), Header=%03d\n", 7698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei addr, mvi->slot_dma, tag); 7708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, "Command Header[%03d]:\n", tag); 7718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*mvs_cmd_hdr */ 7728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(sizeof(struct mvs_cmd_hdr), (u8 *)(&mvi->slot[tag]), 7738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u32) mvi->slot_dma + tag * sizeof(struct mvs_cmd_hdr)); 7748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*1.command table area */ 7758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, "+---->Command Table :\n"); 7768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(slot->cmd_size, (u8 *) slot->buf, (u32) slot->buf_dma); 7778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*2.open address frame area */ 7788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, "+---->Open Address Frame :\n"); 7798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(MVS_OAF_SZ, (u8 *) slot->buf + slot->cmd_size, 7808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u32) slot->buf_dma + slot->cmd_size); 7818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*3.status buffer */ 7828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hba_sb_dump(mvi, tag, proto); 7838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*4.PRD table */ 7848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, "+---->PRD table :\n"); 7858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(sizeof(struct mvs_prd) * slot->n_elem, 7868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u8 *) slot->buf + slot->cmd_size + MVS_OAF_SZ, 7878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u32) slot->buf_dma + slot->cmd_size + MVS_OAF_SZ); 7888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 7898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 7908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 7918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_hba_cq_dump(struct mvs_info *mvi) 7928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 7938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#if _MV_DUMP 7948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u64 addr; 7958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs; 7968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct pci_dev *pdev = mvi->pdev; 7978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 entry = mvi->rx_cons + 1; 7988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 rx_desc = le32_to_cpu(mvi->rx[entry]); 7998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 8008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*Completion Queue */ 8018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei addr = mr32(RX_HI) << 16 << 16 | mr32(RX_LO); 8028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, "Completion Task = 0x%08X\n", 8038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u32) mvi->slot_info[rx_desc & RXQ_SLOT_MASK].task); 8048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, 8058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "Completion List Base Address=0x%llX (PA), " 8068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "CQ_Entry=%04d, CQ_WP=0x%08X\n", 8078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei addr, entry - 1, mvi->rx[0]); 8088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(sizeof(u32), (u8 *)(&rx_desc), 8098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->rx_dma + sizeof(u32) * entry); 8108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 8118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 8128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 8138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_hba_interrupt_enable(struct mvs_info *mvi) 8148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 8158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs; 8168f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tmp; 8178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 8188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mr32(GBL_CTL); 8198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 8208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(GBL_CTL, tmp | INT_EN); 8218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 8228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 8238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_hba_interrupt_disable(struct mvs_info *mvi) 8248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 8258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs; 8268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tmp; 8278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 8288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mr32(GBL_CTL); 8298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 8308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(GBL_CTL, tmp & ~INT_EN); 8318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 8328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 8338f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_int_rx(struct mvs_info *mvi, bool self_clear); 834b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 835b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik/* move to PCI layer or libata core? */ 836b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic int pci_go_64(struct pci_dev *pdev) 837b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 838b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik int rc; 839b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 840b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { 841b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); 842b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) { 843b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 844b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) { 845b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 846b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik "64-bit DMA enable failed\n"); 847b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 848b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 849b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 850b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } else { 851b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = pci_set_dma_mask(pdev, DMA_32BIT_MASK); 852b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) { 853b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 854b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik "32-bit DMA enable failed\n"); 855b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 856b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 857b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK); 858b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) { 859b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dev_printk(KERN_ERR, &pdev->dev, 860b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik "32-bit consistent DMA enable failed\n"); 861b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 862b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 863b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 864b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 865b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 866b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 867b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 8688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_tag_clear(struct mvs_info *mvi, u32 tag) 869b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 8708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->tag_in = (mvi->tag_in + 1) & (MVS_SLOTS - 1); 8718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->tags[mvi->tag_in] = tag; 872b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 873b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 8748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_tag_free(struct mvs_info *mvi, u32 tag) 875b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 8768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->tag_out = (mvi->tag_out - 1) & (MVS_SLOTS - 1); 877b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 878b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 8798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out) 880b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 8818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (mvi->tag_out != mvi->tag_in) { 8828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei *tag_out = mvi->tags[mvi->tag_out]; 8838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->tag_out = (mvi->tag_out + 1) & (MVS_SLOTS - 1); 8848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return 0; 8858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 8868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return -EBUSY; 887b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 888b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 8898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_tag_init(struct mvs_info *mvi) 890b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 8918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei int i; 8928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei for (i = 0; i < MVS_SLOTS; ++i) 8938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->tags[i] = i; 8948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->tag_out = 0; 8958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->tag_in = MVS_SLOTS - 1; 896b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 897b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 8988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#ifndef MVS_DISABLE_NVRAM 8998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_eep_read(void __iomem *regs, u32 addr, u32 *data) 900b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 901b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik int timeout = 1000; 902b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 903b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (addr & ~SPI_ADDR_MASK) 904b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return -EINVAL; 905b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 906b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik writel(addr, regs + SPI_CMD); 907b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik writel(TWSI_RD, regs + SPI_CTL); 908b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 909b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik while (timeout-- > 0) { 910b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (readl(regs + SPI_CTL) & TWSI_RDY) { 911b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik *data = readl(regs + SPI_DATA); 912b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return 0; 913b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 914b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 915b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik udelay(10); 916b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 917b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 918b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return -EBUSY; 919b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 920b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 9218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_eep_read_buf(void __iomem *regs, u32 addr, 9228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void *buf, u32 buflen) 923b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 9248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 addr_end, tmp_addr, i, j; 925b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u32 tmp = 0; 926b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik int rc; 927b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u8 *tmp8, *buf8 = buf; 928b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 929b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik addr_end = addr + buflen; 930b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp_addr = ALIGN(addr, 4); 931b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (addr > 0xff) 932b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return -EINVAL; 933b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 934b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik j = addr & 0x3; 935b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (j) { 936b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = mvs_eep_read(regs, tmp_addr, &tmp); 937b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) 938b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 939b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 9408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp8 = (u8 *)&tmp; 941b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik for (i = j; i < 4; i++) 942b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik *buf8++ = tmp8[i]; 943b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 944b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp_addr += 4; 945b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 946b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 947b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik for (j = ALIGN(addr_end, 4); tmp_addr < j; tmp_addr += 4) { 948b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = mvs_eep_read(regs, tmp_addr, &tmp); 949b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) 950b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 951b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 952b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik memcpy(buf8, &tmp, 4); 953b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf8 += 4; 954b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 955b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 956b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (tmp_addr < addr_end) { 957b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = mvs_eep_read(regs, tmp_addr, &tmp); 958b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) 959b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 960b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 9618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp8 = (u8 *)&tmp; 962b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik j = addr_end - tmp_addr; 963b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik for (i = 0; i < j; i++) 964b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik *buf8++ = tmp8[i]; 965b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 966b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp_addr += 4; 967b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 968b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 969b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return 0; 970b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 9718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 972b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 9738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_nvram_read(struct mvs_info *mvi, u32 addr, 9748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void *buf, u32 buflen) 975b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 9768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#ifndef MVS_DISABLE_NVRAM 977b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void __iomem *regs = mvi->regs; 978b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik int rc, i; 9798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 sum; 980b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u8 hdr[2], *tmp; 981b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik const char *msg; 982b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 983b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = mvs_eep_read_buf(regs, addr, &hdr, 2); 984b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) { 985b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik msg = "nvram hdr read failed"; 986b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 987b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 988b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = mvs_eep_read_buf(regs, addr + 2, buf, buflen); 989b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) { 990b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik msg = "nvram read failed"; 991b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 992b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 993b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 9948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (hdr[0] != 0x5A) { 9958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* entry id */ 996b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik msg = "invalid nvram entry id"; 997b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = -ENOENT; 998b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 999b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1000b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1001b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp = buf; 10028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sum = ((u32)hdr[0]) + ((u32)hdr[1]); 1003b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik for (i = 0; i < buflen; i++) 10048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sum += ((u32)tmp[i]); 1005b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1006b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (sum) { 1007b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik msg = "nvram checksum failure"; 1008b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = -EILSEQ; 1009b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 1010b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1011b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1012b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return 0; 1013b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1014b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out: 1015b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dev_printk(KERN_ERR, &mvi->pdev->dev, "%s", msg); 1016b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 10178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#else 10188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* FIXME , For SAS target mode */ 10198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei memcpy(buf, "\x00\x00\xab\x11\x30\x04\x05\x50", 8); 10208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return 0; 10218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 10228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 10238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 10248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_bytes_dmaed(struct mvs_info *mvi, int i) 10258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 10268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_phy *phy = &mvi->phy[i]; 10278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 10288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (!phy->phy_attached) 10298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return; 10308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 10318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy->phy_type & PORT_TYPE_SAS) { 10328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct sas_identify_frame *id; 10338f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 10348f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei id = (struct sas_identify_frame *)phy->frame_rcvd; 10358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei id->dev_type = phy->identify.device_type; 10368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei id->initiator_bits = SAS_PROTOCOL_ALL; 10378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei id->target_bits = phy->identify.target_port_protocols; 10388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } else if (phy->phy_type & PORT_TYPE_SATA) { 10398f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* TODO */ 10408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 10418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->sas.sas_phy[i]->frame_rcvd_size = phy->frame_rcvd_size; 10428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->sas.notify_port_event(mvi->sas.sas_phy[i], 10438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORTE_BYTES_DMAED); 10448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 10458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 10468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_scan_finished(struct Scsi_Host *shost, unsigned long time) 10478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 10488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* give the phy enabling interrupt event time to come in (1s 10498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * is empirically about all it takes) */ 10508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (time < HZ) 10518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return 0; 10528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* Wait for discovery to finish */ 10538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei scsi_flush_work(shost); 10548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return 1; 10558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 10568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 10578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_scan_start(struct Scsi_Host *shost) 10588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 10598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei int i; 10608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_info *mvi = SHOST_TO_SAS_HA(shost)->lldd_ha; 10618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 10628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei for (i = 0; i < mvi->chip->n_phy; ++i) { 10638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_bytes_dmaed(mvi, i); 10648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 10658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 10668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 10678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_sas_slave_alloc(struct scsi_device *scsi_dev) 10688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 10698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei int rc; 10708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 10718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei rc = sas_slave_alloc(scsi_dev); 10728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 10738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return rc; 1074b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1075b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1076b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic void mvs_int_port(struct mvs_info *mvi, int port_no, u32 events) 1077b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 10788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct pci_dev *pdev = mvi->pdev; 10798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct sas_ha_struct *sas_ha = &mvi->sas; 10808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_phy *phy = &mvi->phy[port_no]; 10818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct asd_sas_phy *sas_phy = &phy->sas_phy; 10828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 10838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->irq_status = mvs_read_port_irq_stat(mvi, port_no); 10848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* 10858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * events is port event now , 10868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * we need check the interrupt status which belongs to per port. 10878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei */ 10888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, 10898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "Port %d Event = %X\n", 10908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei port_no, phy->irq_status); 10918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 10928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy->irq_status & (PHYEV_POOF | PHYEV_DEC_ERR)) { 10938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (!mvs_is_phy_ready(mvi, port_no)) { 10948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sas_phy_disconnected(sas_phy); 10958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sas_ha->notify_phy_event(sas_phy, PHYE_LOSS_OF_SIGNAL); 10968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } else 10978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_phy_control(sas_phy, PHY_FUNC_LINK_RESET, NULL); 10988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 10998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (!(phy->irq_status & PHYEV_DEC_ERR)) { 11008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy->irq_status & PHYEV_COMWAKE) { 11018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tmp = mvs_read_port_irq_mask(mvi, port_no); 11028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_irq_mask(mvi, port_no, 11038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp | PHYEV_SIG_FIS); 11048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 11058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy->irq_status & (PHYEV_SIG_FIS | PHYEV_ID_DONE)) { 11068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->phy_status = mvs_is_phy_ready(mvi, port_no); 11078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy->phy_status) { 11088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_detect_porttype(mvi, port_no); 11098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 11108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy->phy_type & PORT_TYPE_SATA) { 11118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tmp = mvs_read_port_irq_mask(mvi, 11128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei port_no); 11138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp &= ~PHYEV_SIG_FIS; 11148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_irq_mask(mvi, 11158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei port_no, tmp); 11168f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 11178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 11188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_update_phyinfo(mvi, port_no, 0); 11198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sas_ha->notify_phy_event(sas_phy, 11208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHYE_OOB_DONE); 11218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_bytes_dmaed(mvi, port_no); 11228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } else { 11238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, 11248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "plugin interrupt but phy is gone\n"); 11258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_phy_control(sas_phy, PHY_FUNC_LINK_RESET, 11268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei NULL); 11278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 11288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } else if (phy->irq_status & PHYEV_BROAD_CH) 11298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sas_ha->notify_port_event(sas_phy, 11308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PORTE_BROADCAST_RCVD); 11318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 11328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_irq_stat(mvi, port_no, phy->irq_status); 1133b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1134b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1135b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic void mvs_int_sata(struct mvs_info *mvi) 1136b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 1137b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* FIXME */ 1138b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1139b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1140b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic void mvs_slot_free(struct mvs_info *mvi, struct sas_task *task, 11418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_slot_info *slot, u32 slot_idx) 1142b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 11438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (!sas_protocol_ata(task->task_proto)) 11448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (slot->n_elem) 11458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei pci_unmap_sg(mvi->pdev, task->scatter, 11468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->n_elem, task->data_dir); 1147b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1148b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik switch (task->task_proto) { 1149b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik case SAS_PROTOCOL_SMP: 1150b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_unmap_sg(mvi->pdev, &task->smp_task.smp_resp, 1, 1151b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PCI_DMA_FROMDEVICE); 1152b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_unmap_sg(mvi->pdev, &task->smp_task.smp_req, 1, 1153b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PCI_DMA_TODEVICE); 1154b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik break; 1155b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1156b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik case SAS_PROTOCOL_SATA: 1157b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik case SAS_PROTOCOL_STP: 1158b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik case SAS_PROTOCOL_SSP: 1159b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik default: 1160b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* do nothing */ 1161b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik break; 1162b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1163b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 11648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->task = NULL; 1165b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_tag_clear(mvi, slot_idx); 1166b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1167b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1168b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic void mvs_slot_err(struct mvs_info *mvi, struct sas_task *task, 11698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 slot_idx) 1170b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 11718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; 11728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u64 err_dw0 = *(u32 *) slot->response; 11738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs; 11748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tmp; 11758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 11768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (err_dw0 & CMD_ISS_STPD) 11778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (sas_protocol_ata(task->task_proto)) { 11788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mr32(INT_STAT_SRS); 11798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(INT_STAT_SRS, tmp & 0xFFFF); 11808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 11818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 11828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hba_sb_dump(mvi, slot_idx, task->task_proto); 1183b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1184b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 11858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc) 1186b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 11878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 slot_idx = rx_desc & RXQ_SLOT_MASK; 1188b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; 1189b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct sas_task *task = slot->task; 1190b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct task_status_struct *tstat = &task->task_status; 11918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_port *port = &mvi->port[task->dev->port->id]; 1192b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik bool aborted; 11938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void *to; 1194b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1195b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik spin_lock(&task->task_state_lock); 1196b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED; 1197b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!aborted) { 1198b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik task->task_state_flags &= 11998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR); 1200b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik task->task_state_flags |= SAS_TASK_STATE_DONE; 1201b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1202b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik spin_unlock(&task->task_state_lock); 1203b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1204b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (aborted) 12058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return -1; 1206b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1207b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik memset(tstat, 0, sizeof(*tstat)); 1208b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tstat->resp = SAS_TASK_COMPLETE; 1209b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 12108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 12118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (unlikely(!port->port_attached)) { 12128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tstat->stat = SAS_PHY_DOWN; 12138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei goto out; 12148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 12158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1216b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* error info record present */ 12178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if ((rx_desc & RXQ_ERR) && (*(u64 *) slot->response)) { 1218b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tstat->stat = SAM_CHECK_COND; 1219b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_slot_err(mvi, task, slot_idx); 1220b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto out; 1221b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1222b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1223b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik switch (task->task_proto) { 1224b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik case SAS_PROTOCOL_SSP: 1225b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* hw says status == 0, datapres == 0 */ 12268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (rx_desc & RXQ_GOOD) { 1227b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tstat->stat = SAM_GOOD; 12288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tstat->resp = SAS_TASK_COMPLETE; 12298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 1230b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* response frame present */ 1231b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik else if (rx_desc & RXQ_RSP) { 1232b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct ssp_response_iu *iu = 12338f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->response + sizeof(struct mvs_err_info); 1234b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_ssp_task_response(&mvi->pdev->dev, task, iu); 1235b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1236b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1237b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* should never happen? */ 1238b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik else 1239b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tstat->stat = SAM_CHECK_COND; 1240b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik break; 1241b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 12428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei case SAS_PROTOCOL_SMP: { 12438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct scatterlist *sg_resp = &task->smp_task.smp_resp; 12448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tstat->stat = SAM_GOOD; 12458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei to = kmap_atomic(sg_page(sg_resp), KM_IRQ0); 12468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei memcpy(to + sg_resp->offset, 12478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->response + sizeof(struct mvs_err_info), 12488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sg_dma_len(sg_resp)); 12498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei kunmap_atomic(to, KM_IRQ0); 12508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei break; 12518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 1252b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1253b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik case SAS_PROTOCOL_SATA: 1254b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik case SAS_PROTOCOL_STP: 12558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: { 12568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct ata_task_resp *resp = 12578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (struct ata_task_resp *)tstat->buf; 12588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 12598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if ((rx_desc & (RXQ_DONE | RXQ_ERR | RXQ_ATTN)) == 12608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei RXQ_DONE) 12618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tstat->stat = SAM_GOOD; 12628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 12638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tstat->stat = SAM_CHECK_COND; 12648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 12658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei resp->frame_len = sizeof(struct dev_to_host_fis); 12668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei memcpy(&resp->ending_fis[0], 12678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei SATA_RECEIVED_D2H_FIS(port->taskfileset), 12688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sizeof(struct dev_to_host_fis)); 12698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (resp->ending_fis[2] & ATA_ERR) 12708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(16, resp->ending_fis, 0); 12718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei break; 12728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 1273b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1274b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik default: 1275b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tstat->stat = SAM_CHECK_COND; 1276b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik break; 1277b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1278b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1279b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikout: 1280b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_slot_free(mvi, task, slot, slot_idx); 1281b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik task->task_done(task); 12828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return tstat->stat; 1283b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1284b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1285b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic void mvs_int_full(struct mvs_info *mvi) 1286b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 1287b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void __iomem *regs = mvi->regs; 1288b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u32 tmp, stat; 1289b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik int i; 1290b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1291b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik stat = mr32(INT_STAT); 1292b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 12938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_int_rx(mvi, false); 12948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1295b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik for (i = 0; i < MVS_MAX_PORTS; i++) { 1296b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp = (stat >> i) & (CINT_PORT | CINT_PORT_STOPPED); 1297b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (tmp) 1298b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_int_port(mvi, i, tmp); 1299b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1300b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1301b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (stat & CINT_SRS) 1302b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_int_sata(mvi); 1303b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1304b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(INT_STAT, stat); 1305b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1306b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 13078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_int_rx(struct mvs_info *mvi, bool self_clear) 1308b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 13098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs; 1310b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u32 rx_prod_idx, rx_desc; 1311b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik bool attn = false; 13128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct pci_dev *pdev = mvi->pdev; 1313b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1314b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* the first dword in the RX ring is special: it contains 1315b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * a mirror of the hardware's RX producer index, so that 1316b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * we don't have to stall the CPU reading that register. 1317b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * The actual RX ring is offset by one dword, due to this. 1318b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 13198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei rx_prod_idx = mr32(RX_CONS_IDX) & RX_RING_SZ_MASK; 1320b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rx_prod_idx == 0xfff) { /* h/w hasn't touched RX ring yet */ 1321b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->rx_cons = 0xfff; 13228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return 0; 1323b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 13248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 13258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* The CMPL_Q may come late, read from register and try again 13268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * note: if coalescing is enabled, 13278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * it will need to read from register every time for sure 13288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei */ 13298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (mvi->rx_cons == rx_prod_idx) 13308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return 0; 13318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1332b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (mvi->rx_cons == 0xfff) 1333b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->rx_cons = MVS_RX_RING_SZ - 1; 1334b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1335b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik while (mvi->rx_cons != rx_prod_idx) { 13368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1337b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* increment our internal RX consumer pointer */ 1338b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->rx_cons = (mvi->rx_cons + 1) & (MVS_RX_RING_SZ - 1); 1339b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1340b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rx_desc = le32_to_cpu(mvi->rx[mvi->rx_cons + 1]); 1341b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 13428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hba_cq_dump(mvi); 1343b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 13448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (unlikely(rx_desc & RXQ_DONE)) 13458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_slot_complete(mvi, rx_desc); 13468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (rx_desc & RXQ_ATTN) { 1347b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik attn = true; 13488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, "ATTN %X\n", 13498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei rx_desc); 13508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } else if (rx_desc & RXQ_ERR) { 13518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, "RXQ_ERR %X\n", 13528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei rx_desc); 13538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 1354b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1355b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1356b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (attn && self_clear) 1357b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_int_full(mvi); 1358b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 13598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return 0; 1360b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1361b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1362b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic irqreturn_t mvs_interrupt(int irq, void *opaque) 1363b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 1364b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_info *mvi = opaque; 1365b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void __iomem *regs = mvi->regs; 1366b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u32 stat; 1367b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1368b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik stat = mr32(GBL_INT_STAT); 13698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 13708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* clear CMD_CMPLT ASAP */ 13718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32_f(INT_STAT, CINT_DONE); 13728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1373b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (stat == 0 || stat == 0xffffffff) 1374b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return IRQ_NONE; 1375b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1376b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik spin_lock(&mvi->lock); 1377b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1378b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_int_full(mvi); 1379b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1380b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik spin_unlock(&mvi->lock); 1381b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1382b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return IRQ_HANDLED; 1383b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1384b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 13858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#ifndef MVS_DISABLE_MSI 1386b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic irqreturn_t mvs_msi_interrupt(int irq, void *opaque) 1387b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 1388b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_info *mvi = opaque; 1389b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1390b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik spin_lock(&mvi->lock); 1391b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1392b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_int_rx(mvi, true); 1393b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1394b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik spin_unlock(&mvi->lock); 1395b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1396b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return IRQ_HANDLED; 1397b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 13988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 1399b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1400b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstruct mvs_task_exec_info { 14018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct sas_task *task; 14028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_cmd_hdr *hdr; 14038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_port *port; 14048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tag; 14058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei int n_elem; 1406b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 1407b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 14088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_task_prep_smp(struct mvs_info *mvi, 14098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_task_exec_info *tei) 1410b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 14118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei int elem, rc, i; 14128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct sas_task *task = tei->task; 1413b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_cmd_hdr *hdr = tei->hdr; 1414b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct scatterlist *sg_req, *sg_resp; 14158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 req_len, resp_len, tag = tei->tag; 14168f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void *buf_tmp; 14178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u8 *buf_oaf; 14188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dma_addr_t buf_tmp_dma; 14198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_prd *buf_prd; 14208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct scatterlist *sg; 14218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_slot_info *slot = &mvi->slot_info[tag]; 14228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct asd_sas_port *sas_port = task->dev->port; 14238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); 14248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#if _MV_DUMP 14258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u8 *buf_cmd; 14268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void *from; 14278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 1428b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* 1429b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * DMA-map SMP request, response buffers 1430b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 14318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sg_req = &task->smp_task.smp_req; 1432b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik elem = pci_map_sg(mvi->pdev, sg_req, 1, PCI_DMA_TODEVICE); 1433b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!elem) 1434b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return -ENOMEM; 1435b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik req_len = sg_dma_len(sg_req); 1436b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 14378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sg_resp = &task->smp_task.smp_resp; 1438b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik elem = pci_map_sg(mvi->pdev, sg_resp, 1, PCI_DMA_FROMDEVICE); 1439b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!elem) { 1440b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = -ENOMEM; 1441b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 1442b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1443b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik resp_len = sg_dma_len(sg_resp); 1444b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1445b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* must be in dwords */ 1446b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if ((req_len & 0x3) || (resp_len & 0x3)) { 1447b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = -EINVAL; 1448b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out_2; 1449b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1450b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1451b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* 14528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs 1453b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 1454b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 14558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ************** */ 14568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_tmp = slot->buf; 14578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_tmp_dma = slot->buf_dma; 1458b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 14598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#if _MV_DUMP 14608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_cmd = buf_tmp; 14618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); 14628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_tmp += req_len; 14638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_tmp_dma += req_len; 14648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->cmd_size = req_len; 14658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#else 14668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->cmd_tbl = cpu_to_le64(sg_dma_address(sg_req)); 14678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 14688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 14698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ 14708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_oaf = buf_tmp; 14718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->open_frame = cpu_to_le64(buf_tmp_dma); 14728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 14738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_tmp += MVS_OAF_SZ; 14748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_tmp_dma += MVS_OAF_SZ; 14758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 14768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 3: PRD table ********************************************* */ 14778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_prd = buf_tmp; 14788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (tei->n_elem) 14798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->prd_tbl = cpu_to_le64(buf_tmp_dma); 14808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 14818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->prd_tbl = 0; 14828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 14838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei i = sizeof(struct mvs_prd) * tei->n_elem; 14848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_tmp += i; 14858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_tmp_dma += i; 14868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 14878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 4: status buffer (larger the PRD, smaller this buf) ****** */ 14888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->response = buf_tmp; 14898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->status_buf = cpu_to_le64(buf_tmp_dma); 14908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 14918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* 14928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * Fill in TX ring and command slot header 14938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei */ 14948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->tx = mvi->tx_prod; 14958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->tx[mvi->tx_prod] = cpu_to_le32((TXQ_CMD_SMP << TXQ_CMD_SHIFT) | 14968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei TXQ_MODE_I | tag | 14978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (sas_port->phy_mask << TXQ_PHY_SHIFT)); 14988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 14998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->flags |= flags; 15008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | ((req_len - 4) / 4)); 1501b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->tags = cpu_to_le32(tag); 1502b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->data_len = 0; 1503b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 15048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* generate open address frame hdr (first 12 bytes) */ 15058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_oaf[0] = (1 << 7) | (0 << 4) | 0x01; /* initiator, SMP, ftype 1h */ 15068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_oaf[1] = task->dev->linkrate & 0xf; 15078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei *(u16 *)(buf_oaf + 2) = 0xFFFF; /* SAS SPEC */ 15088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei memcpy(buf_oaf + 4, task->dev->sas_addr, SAS_ADDR_SIZE); 15098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* fill in PRD (scatter/gather) table, if any */ 15118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei for_each_sg(task->scatter, sg, tei->n_elem, i) { 15128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_prd->addr = cpu_to_le64(sg_dma_address(sg)); 15138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_prd->len = cpu_to_le32(sg_dma_len(sg)); 15148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_prd++; 15158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 15168f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#if _MV_DUMP 15188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* copy cmd table */ 15198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei from = kmap_atomic(sg_page(sg_req), KM_IRQ0); 15208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei memcpy(buf_cmd, from + sg_req->offset, req_len); 15218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei kunmap_atomic(from, KM_IRQ0); 15228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 1523b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return 0; 1524b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1525b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out_2: 1526b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_unmap_sg(mvi->pdev, &tei->task->smp_task.smp_resp, 1, 1527b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PCI_DMA_FROMDEVICE); 1528b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out: 1529b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_unmap_sg(mvi->pdev, &tei->task->smp_task.smp_req, 1, 1530b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik PCI_DMA_TODEVICE); 1531b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 1532b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1533b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 15348f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_free_reg_set(struct mvs_info *mvi, struct mvs_port *port) 15358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 15368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs; 15378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tmp, offs; 15388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u8 *tfs = &port->taskfileset; 15398f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (*tfs == MVS_ID_NOT_MAPPED) 15418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return; 15428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei offs = 1U << ((*tfs & 0x0f) + PCS_EN_SATA_REG_SHIFT); 15448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (*tfs < 16) { 15458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mr32(PCS); 15468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(PCS, tmp & ~offs); 15478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } else { 15488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mr32(CTL); 15498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(CTL, tmp & ~offs); 15508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 15518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mr32(INT_STAT_SRS) & (1U << *tfs); 15538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (tmp) 15548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(INT_STAT_SRS, tmp); 15558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei *tfs = MVS_ID_NOT_MAPPED; 15578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 15588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u8 mvs_assign_reg_set(struct mvs_info *mvi, struct mvs_port *port) 15608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 15618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei int i; 15628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tmp, offs; 15638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs; 15648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (port->taskfileset != MVS_ID_NOT_MAPPED) 15668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return 0; 15678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mr32(PCS); 15698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei for (i = 0; i < mvi->chip->srs_sz; i++) { 15718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (i == 16) 15728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mr32(CTL); 15738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei offs = 1U << ((i & 0x0f) + PCS_EN_SATA_REG_SHIFT); 15748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (!(tmp & offs)) { 15758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei port->taskfileset = i; 15768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (i < 16) 15788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(PCS, tmp | offs); 15798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 15808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(CTL, tmp | offs); 15818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mr32(INT_STAT_SRS) & (1U << i); 15828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (tmp) 15838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(INT_STAT_SRS, tmp); 15848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return 0; 15858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 15868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 15878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return MVS_ID_NOT_MAPPED; 15888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 15898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_get_ncq_tag(struct sas_task *task) 15918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 15928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tag = 0; 15938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct ata_queued_cmd *qc = task->uldd_task; 15948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (qc) 15968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tag = qc->tag; 15978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return tag; 15998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 16008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1601b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic int mvs_task_prep_ata(struct mvs_info *mvi, 1602b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_task_exec_info *tei) 1603b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 1604b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct sas_task *task = tei->task; 1605b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct domain_device *dev = task->dev; 1606b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_cmd_hdr *hdr = tei->hdr; 1607b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct asd_sas_port *sas_port = dev->port; 16088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_slot_info *slot; 1609b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct scatterlist *sg; 1610b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_prd *buf_prd; 16118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_port *port = tei->port; 16128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tag = tei->tag; 16138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); 1614b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void *buf_tmp; 1615b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u8 *buf_cmd, *buf_oaf; 1616b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_addr_t buf_tmp_dma; 16178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 i, req_len, resp_len; 16188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei const u32 max_resp_len = SB_RFB_MAX; 16198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 16208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (mvs_assign_reg_set(mvi, port) == MVS_ID_NOT_MAPPED) 16218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return -EBUSY; 1622b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 16238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot = &mvi->slot_info[tag]; 16248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->tx = mvi->tx_prod; 16258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag | 16268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (TXQ_CMD_STP << TXQ_CMD_SHIFT) | 16278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (sas_port->phy_mask << TXQ_PHY_SHIFT) | 16288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (port->taskfileset << TXQ_SRS_SHIFT)); 1629b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1630b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (task->ata_task.use_ncq) 1631b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik flags |= MCH_FPDMA; 16328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) { 16338f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (task->ata_task.fis.command != ATA_CMD_ID_ATAPI) 16348f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei flags |= MCH_ATAPI; 16358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 16368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1637b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* FIXME: fill in port multiplier number */ 1638b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1639b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->flags = cpu_to_le32(flags); 16408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 16418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* FIXME: the low order order 5 bits for the TAG if enable NCQ */ 16428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (task->ata_task.use_ncq) { 16438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->tags = cpu_to_le32(mvs_get_ncq_tag(task)); 16448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*Fill in task file */ 16458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei task->ata_task.fis.sector_count = hdr->tags << 3; 16468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } else 16478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->tags = cpu_to_le32(tag); 1648b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->data_len = cpu_to_le32(task->total_xfer_len); 1649b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1650b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* 1651b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs 1652b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 1653b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 16548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 1: command table area (MVS_ATA_CMD_SZ bytes) ************** */ 16558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_cmd = buf_tmp = slot->buf; 1656b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma = slot->buf_dma; 1657b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1658b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); 1659b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1660b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp += MVS_ATA_CMD_SZ; 1661b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma += MVS_ATA_CMD_SZ; 16628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#if _MV_DUMP 16638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->cmd_size = MVS_ATA_CMD_SZ; 16648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 1665b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 16668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ 1667b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* used for STP. unused for SATA? */ 1668b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_oaf = buf_tmp; 1669b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->open_frame = cpu_to_le64(buf_tmp_dma); 1670b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1671b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp += MVS_OAF_SZ; 1672b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma += MVS_OAF_SZ; 1673b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 16748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 3: PRD table ********************************************* */ 1675b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_prd = buf_tmp; 16768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (tei->n_elem) 16778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->prd_tbl = cpu_to_le64(buf_tmp_dma); 16788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 16798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->prd_tbl = 0; 1680b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1681b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik i = sizeof(struct mvs_prd) * tei->n_elem; 1682b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp += i; 1683b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma += i; 1684b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 16858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 4: status buffer (larger the PRD, smaller this buf) ****** */ 1686b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* FIXME: probably unused, for SATA. kept here just in case 1687b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * we get a STP/SATA error information record 1688b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 1689b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik slot->response = buf_tmp; 1690b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->status_buf = cpu_to_le64(buf_tmp_dma); 1691b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 16928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei req_len = sizeof(struct host_to_dev_fis); 1693b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik resp_len = MVS_SLOT_BUF_SZ - MVS_ATA_CMD_SZ - 16948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sizeof(struct mvs_err_info) - i; 1695b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1696b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* request, response lengths */ 16978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei resp_len = min(resp_len, max_resp_len); 1698b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | (req_len / 4)); 1699b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 17008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei task->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */ 1701b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* fill in command FIS and ATAPI CDB */ 17028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei memcpy(buf_cmd, &task->ata_task.fis, sizeof(struct host_to_dev_fis)); 17038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) 17048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei memcpy(buf_cmd + STP_ATAPI_CMD, 17058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei task->ata_task.atapi_packet, 16); 17068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 17078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* generate open address frame hdr (first 12 bytes) */ 17088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_oaf[0] = (1 << 7) | (2 << 4) | 0x1; /* initiator, STP, ftype 1h */ 17098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_oaf[1] = task->dev->linkrate & 0xf; 17108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei *(u16 *)(buf_oaf + 2) = cpu_to_be16(tag); 17118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei memcpy(buf_oaf + 4, task->dev->sas_addr, SAS_ADDR_SIZE); 1712b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1713b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* fill in PRD (scatter/gather) table, if any */ 17148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei for_each_sg(task->scatter, sg, tei->n_elem, i) { 1715b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_prd->addr = cpu_to_le64(sg_dma_address(sg)); 1716b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_prd->len = cpu_to_le32(sg_dma_len(sg)); 1717b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_prd++; 1718b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1719b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1720b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return 0; 1721b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1722b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1723b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic int mvs_task_prep_ssp(struct mvs_info *mvi, 1724b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_task_exec_info *tei) 1725b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 1726b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct sas_task *task = tei->task; 1727b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_cmd_hdr *hdr = tei->hdr; 17288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_port *port = tei->port; 1729b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_slot_info *slot; 1730b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct scatterlist *sg; 1731b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_prd *buf_prd; 1732b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct ssp_frame_hdr *ssp_hdr; 1733b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void *buf_tmp; 1734b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u8 *buf_cmd, *buf_oaf, fburst = 0; 1735b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_addr_t buf_tmp_dma; 1736b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u32 flags; 17378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 resp_len, req_len, i, tag = tei->tag; 17388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei const u32 max_resp_len = SB_RFB_MAX; 1739b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1740b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik slot = &mvi->slot_info[tag]; 1741b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 17428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->tx = mvi->tx_prod; 17438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag | 17448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (TXQ_CMD_SSP << TXQ_CMD_SHIFT) | 17458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (port->wide_port_phymap << TXQ_PHY_SHIFT)); 1746b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1747b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik flags = MCH_RETRY; 1748b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (task->ssp_task.enable_first_burst) { 1749b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik flags |= MCH_FBURST; 1750b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik fburst = (1 << 7); 1751b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1752b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->flags = cpu_to_le32(flags | 17538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (tei->n_elem << MCH_PRD_LEN_SHIFT) | 17548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (MCH_SSP_FR_CMD << MCH_SSP_FR_TYPE_SHIFT)); 1755b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1756b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->tags = cpu_to_le32(tag); 1757b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->data_len = cpu_to_le32(task->total_xfer_len); 1758b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1759b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* 1760b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs 1761b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 1762b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 17638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ************** */ 17648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_cmd = buf_tmp = slot->buf; 1765b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma = slot->buf_dma; 1766b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1767b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); 1768b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1769b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp += MVS_SSP_CMD_SZ; 1770b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma += MVS_SSP_CMD_SZ; 17718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#if _MV_DUMP 17728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->cmd_size = MVS_SSP_CMD_SZ; 17738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 1774b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 17758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ 1776b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_oaf = buf_tmp; 1777b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->open_frame = cpu_to_le64(buf_tmp_dma); 1778b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1779b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp += MVS_OAF_SZ; 1780b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma += MVS_OAF_SZ; 1781b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 17828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 3: PRD table ********************************************* */ 1783b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_prd = buf_tmp; 17848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (tei->n_elem) 17858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->prd_tbl = cpu_to_le64(buf_tmp_dma); 17868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 17878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->prd_tbl = 0; 1788b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1789b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik i = sizeof(struct mvs_prd) * tei->n_elem; 1790b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp += i; 1791b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma += i; 1792b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 17938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 4: status buffer (larger the PRD, smaller this buf) ****** */ 1794b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik slot->response = buf_tmp; 1795b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->status_buf = cpu_to_le64(buf_tmp_dma); 1796b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1797b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik resp_len = MVS_SLOT_BUF_SZ - MVS_SSP_CMD_SZ - MVS_OAF_SZ - 17988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sizeof(struct mvs_err_info) - i; 17998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei resp_len = min(resp_len, max_resp_len); 18008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 18018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei req_len = sizeof(struct ssp_frame_hdr) + 28; 1802b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1803b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* request, response lengths */ 1804b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | (req_len / 4)); 1805b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1806b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* generate open address frame hdr (first 12 bytes) */ 1807b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_oaf[0] = (1 << 7) | (1 << 4) | 0x1; /* initiator, SSP, ftype 1h */ 1808b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_oaf[1] = task->dev->linkrate & 0xf; 18098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei *(u16 *)(buf_oaf + 2) = cpu_to_be16(tag); 1810b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik memcpy(buf_oaf + 4, task->dev->sas_addr, SAS_ADDR_SIZE); 1811b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 18128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* fill in SSP frame header (Command Table.SSP frame header) */ 18138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei ssp_hdr = (struct ssp_frame_hdr *)buf_cmd; 1814b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik ssp_hdr->frame_type = SSP_COMMAND; 1815b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik memcpy(ssp_hdr->hashed_dest_addr, task->dev->hashed_sas_addr, 1816b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik HASHED_SAS_ADDR_SIZE); 1817b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik memcpy(ssp_hdr->hashed_src_addr, 1818b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik task->dev->port->ha->hashed_sas_addr, HASHED_SAS_ADDR_SIZE); 1819b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik ssp_hdr->tag = cpu_to_be16(tag); 1820b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1821b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* fill in command frame IU */ 1822b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_cmd += sizeof(*ssp_hdr); 1823b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik memcpy(buf_cmd, &task->ssp_task.LUN, 8); 18248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_cmd[9] = fburst | task->ssp_task.task_attr | 18258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (task->ssp_task.task_prio << 3); 1826b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik memcpy(buf_cmd + 12, &task->ssp_task.cdb, 16); 1827b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1828b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* fill in PRD (scatter/gather) table, if any */ 18298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei for_each_sg(task->scatter, sg, tei->n_elem, i) { 1830b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_prd->addr = cpu_to_le64(sg_dma_address(sg)); 1831b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_prd->len = cpu_to_le32(sg_dma_len(sg)); 1832b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_prd++; 1833b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1834b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1835b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return 0; 1836b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1837b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1838b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags) 1839b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 18408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct domain_device *dev = task->dev; 18418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_info *mvi = dev->port->ha->lldd_ha; 18428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct pci_dev *pdev = mvi->pdev; 1843b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void __iomem *regs = mvi->regs; 1844b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_task_exec_info tei; 18458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct sas_task *t = task; 18468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tag = 0xdeadbeef, rc, n_elem = 0; 18478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei unsigned long flags; 18488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 n = num, pass = 0; 1849b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 18508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei spin_lock_irqsave(&mvi->lock, flags); 1851b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 18528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei do { 18538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tei.port = &mvi->port[dev->port->id]; 1854b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 18558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (!tei.port->port_attached) { 18568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct task_status_struct *ts = &t->task_status; 18578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei ts->stat = SAS_PHY_DOWN; 18588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei t->task_done(t); 18598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei rc = 0; 18608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei goto exec_exit; 18618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 18628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (!sas_protocol_ata(t->task_proto)) { 18638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (t->num_scatter) { 18648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei n_elem = pci_map_sg(mvi->pdev, t->scatter, 18658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei t->num_scatter, 18668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei t->data_dir); 18678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (!n_elem) { 18688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei rc = -ENOMEM; 18698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei goto err_out; 18708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 18718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 18728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } else { 18738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei n_elem = t->num_scatter; 18748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 1875b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 18768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei rc = mvs_tag_alloc(mvi, &tag); 18778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (rc) 18788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei goto err_out; 1879b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 18808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->slot_info[tag].task = t; 18818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->slot_info[tag].n_elem = n_elem; 18828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei memset(mvi->slot_info[tag].buf, 0, MVS_SLOT_BUF_SZ); 18838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tei.task = t; 18848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tei.hdr = &mvi->slot[tag]; 18858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tei.tag = tag; 18868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tei.n_elem = n_elem; 18878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 18888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei switch (t->task_proto) { 18898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei case SAS_PROTOCOL_SMP: 18908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei rc = mvs_task_prep_smp(mvi, &tei); 18918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei break; 18928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei case SAS_PROTOCOL_SSP: 18938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei rc = mvs_task_prep_ssp(mvi, &tei); 18948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei break; 18958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei case SAS_PROTOCOL_SATA: 18968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei case SAS_PROTOCOL_STP: 18978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: 18988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei rc = mvs_task_prep_ata(mvi, &tei); 18998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei break; 19008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei default: 19018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_ERR, &pdev->dev, 19028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "unknown sas_task proto: 0x%x\n", 19038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei t->task_proto); 19048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei rc = -EINVAL; 19058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei break; 19068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 1907b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 19088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (rc) 19098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei goto err_out_tag; 1910b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 19118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* TODO: select normal or high priority */ 1912b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 19138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei spin_lock(&t->task_state_lock); 19148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei t->task_state_flags |= SAS_TASK_AT_INITIATOR; 19158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei spin_unlock(&t->task_state_lock); 1916b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 19178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (n == 1) { 19188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei spin_unlock_irqrestore(&mvi->lock, flags); 19198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(TX_PROD_IDX, mvi->tx_prod); 19208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 19218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hba_memory_dump(mvi, tag, t->task_proto); 1922b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 19238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei ++pass; 19248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); 1925b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 19268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (n == 1) 19278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei break; 19288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 19298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei t = list_entry(t->list.next, struct sas_task, list); 19308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } while (--n); 1931b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1932b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return 0; 1933b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1934b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out_tag: 19358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_tag_free(mvi, tag); 1936b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out: 19378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_ERR, &pdev->dev, "mvsas exec failed[%d]!\n", rc); 19388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (!sas_protocol_ata(t->task_proto)) 19398f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (n_elem) 19408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei pci_unmap_sg(mvi->pdev, t->scatter, n_elem, 19418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei t->data_dir); 19428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weiexec_exit: 19438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (pass) 19448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(TX_PROD_IDX, (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1)); 1945b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik spin_unlock_irqrestore(&mvi->lock, flags); 1946b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 1947b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1948b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 19498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic int mvs_task_abort(struct sas_task *task) 19508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 19518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei int rc = 1; 19528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei unsigned long flags; 19538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_info *mvi = task->dev->port->ha->lldd_ha; 19548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct pci_dev *pdev = mvi->pdev; 19558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 19568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei spin_lock_irqsave(&task->task_state_lock, flags); 19578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (task->task_state_flags & SAS_TASK_STATE_DONE) { 19588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei rc = TMF_RESP_FUNC_COMPLETE; 19598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei goto out_done; 19608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 19618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei spin_unlock_irqrestore(&task->task_state_lock, flags); 19628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 19638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*FIXME*/ 19648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei rc = TMF_RESP_FUNC_COMPLETE; 19658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 19668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei switch (task->task_proto) { 19678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei case SAS_PROTOCOL_SMP: 19688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, "SMP Abort! "); 19698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei break; 19708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei case SAS_PROTOCOL_SSP: 19718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, "SSP Abort! "); 19728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei break; 19738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei case SAS_PROTOCOL_SATA: 19748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei case SAS_PROTOCOL_STP: 19758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:{ 19768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, "STP Abort! " 19778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "Dump D2H FIS: \n"); 19788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(sizeof(struct host_to_dev_fis), 19798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (void *)&task->ata_task.fis, 0); 19808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, "Dump ATAPI Cmd : \n"); 19818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(16, task->ata_task.atapi_packet, 0); 19828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei break; 19838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 19848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei default: 19858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei break; 19868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 19878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weiout_done: 19888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return rc; 19898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 19908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1991b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic void mvs_free(struct mvs_info *mvi) 1992b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 1993b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik int i; 1994b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1995b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!mvi) 1996b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return; 1997b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1998b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik for (i = 0; i < MVS_SLOTS; i++) { 1999b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_slot_info *slot = &mvi->slot_info[i]; 2000b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2001b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (slot->buf) 2002b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_free_coherent(&mvi->pdev->dev, MVS_SLOT_BUF_SZ, 2003b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik slot->buf, slot->buf_dma); 2004b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 2005b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2006b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (mvi->tx) 2007b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_free_coherent(&mvi->pdev->dev, 20088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ, 2009b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->tx, mvi->tx_dma); 2010b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (mvi->rx_fis) 2011b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_free_coherent(&mvi->pdev->dev, MVS_RX_FISL_SZ, 2012b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->rx_fis, mvi->rx_fis_dma); 2013b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (mvi->rx) 2014b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_free_coherent(&mvi->pdev->dev, 2015b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sizeof(*mvi->rx) * MVS_RX_RING_SZ, 2016b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->rx, mvi->rx_dma); 2017b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (mvi->slot) 2018b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_free_coherent(&mvi->pdev->dev, 20198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sizeof(*mvi->slot) * MVS_SLOTS, 2020b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->slot, mvi->slot_dma); 20218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#ifdef MVS_ENABLE_PERI 2022b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (mvi->peri_regs) 2023b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik iounmap(mvi->peri_regs); 20248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 2025b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (mvi->regs) 2026b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik iounmap(mvi->regs); 2027b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (mvi->shost) 2028b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik scsi_host_put(mvi->shost); 2029b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik kfree(mvi->sas.sas_port); 2030b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik kfree(mvi->sas.sas_phy); 2031b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik kfree(mvi); 2032b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2033b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2034b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik/* FIXME: locking? */ 2035b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, 2036b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void *funcdata) 2037b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2038b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_info *mvi = sas_phy->ha->lldd_ha; 2039b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik int rc = 0, phy_id = sas_phy->id; 2040b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u32 tmp; 2041b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 20428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mvs_read_phy_ctl(mvi, phy_id); 2043b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2044b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik switch (func) { 20458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei case PHY_FUNC_SET_LINK_RATE:{ 20468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct sas_phy_linkrates *rates = funcdata; 20478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 lrmin = 0, lrmax = 0; 2048b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 20498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei lrmin = (rates->minimum_linkrate << 8); 20508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei lrmax = (rates->maximum_linkrate << 12); 2051b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 20528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (lrmin) { 20538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp &= ~(0xf << 8); 20548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp |= lrmin; 20558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 20568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (lrmax) { 20578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp &= ~(0xf << 12); 20588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp |= lrmax; 20598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 20608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_phy_ctl(mvi, phy_id, tmp); 20618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei break; 2062b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 2063b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2064b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik case PHY_FUNC_HARD_RESET: 2065b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (tmp & PHY_RST_HARD) 2066b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik break; 20678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_phy_ctl(mvi, phy_id, tmp | PHY_RST_HARD); 2068b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik break; 2069b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2070b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik case PHY_FUNC_LINK_RESET: 20718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_phy_ctl(mvi, phy_id, tmp | PHY_RST); 2072b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik break; 2073b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2074b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik case PHY_FUNC_DISABLE: 2075b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik case PHY_FUNC_RELEASE_SPINUP_HOLD: 2076b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik default: 2077b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = -EOPNOTSUPP; 2078b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 2079b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2080b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 2081b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2082b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2083b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id) 2084b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2085b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_phy *phy = &mvi->phy[phy_id]; 2086b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct asd_sas_phy *sas_phy = &phy->sas_phy; 2087b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2088b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_phy->enabled = (phy_id < mvi->chip->n_phy) ? 1 : 0; 2089b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_phy->class = SAS; 2090b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_phy->iproto = SAS_PROTOCOL_ALL; 2091b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_phy->tproto = 0; 2092b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_phy->type = PHY_TYPE_PHYSICAL; 2093b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_phy->role = PHY_ROLE_INITIATOR; 2094b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_phy->oob_mode = OOB_NOT_CONNECTED; 2095b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN; 2096b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2097b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_phy->id = phy_id; 2098b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_phy->sas_addr = &mvi->sas_addr[0]; 2099b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_phy->frame_rcvd = &phy->frame_rcvd[0]; 2100b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_phy->ha = &mvi->sas; 2101b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_phy->lldd_phy = phy; 2102b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2103b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 21048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic struct mvs_info *__devinit mvs_alloc(struct pci_dev *pdev, 21058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei const struct pci_device_id *ent) 2106b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2107b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_info *mvi; 21088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei unsigned long res_start, res_len, res_flag; 2109b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct asd_sas_phy **arr_phy; 2110b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct asd_sas_port **arr_port; 2111b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik const struct mvs_chip_info *chip = &mvs_chips[ent->driver_data]; 2112b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik int i; 2113b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2114b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* 2115b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * alloc and init our per-HBA mvs_info struct 2116b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 2117b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2118b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi = kzalloc(sizeof(*mvi), GFP_KERNEL); 2119b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!mvi) 2120b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return NULL; 2121b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2122b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik spin_lock_init(&mvi->lock); 2123b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->pdev = pdev; 2124b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->chip = chip; 2125b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2126b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (pdev->device == 0x6440 && pdev->revision == 0) 2127b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->flags |= MVF_PHY_PWR_FIX; 2128b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2129b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* 2130b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * alloc and init SCSI, SAS glue 2131b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 2132b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2133b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->shost = scsi_host_alloc(&mvs_sht, sizeof(void *)); 2134b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!mvi->shost) 2135b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 2136b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2137b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik arr_phy = kcalloc(MVS_MAX_PHYS, sizeof(void *), GFP_KERNEL); 2138b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik arr_port = kcalloc(MVS_MAX_PHYS, sizeof(void *), GFP_KERNEL); 2139b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!arr_phy || !arr_port) 2140b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 2141b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2142b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik for (i = 0; i < MVS_MAX_PHYS; i++) { 2143b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_phy_init(mvi, i); 2144b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik arr_phy[i] = &mvi->phy[i].sas_phy; 2145b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik arr_port[i] = &mvi->port[i].sas_port; 2146b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 2147b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2148b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik SHOST_TO_SAS_HA(mvi->shost) = &mvi->sas; 2149b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->shost->transportt = mvs_stt; 21508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->shost->max_id = 21; 2151b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->shost->max_lun = ~0; 21528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->shost->max_channel = 0; 21538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->shost->max_cmd_len = 16; 2154b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2155b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->sas.sas_ha_name = DRV_NAME; 2156b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->sas.dev = &pdev->dev; 2157b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->sas.lldd_module = THIS_MODULE; 2158b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->sas.sas_addr = &mvi->sas_addr[0]; 2159b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->sas.sas_phy = arr_phy; 2160b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->sas.sas_port = arr_port; 2161b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->sas.num_phys = chip->n_phy; 21628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->sas.lldd_max_execute_num = MVS_CHIP_SLOT_SZ - 1; 21638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->sas.lldd_queue_size = MVS_QUEUE_SIZE; 21648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->can_queue = (MVS_CHIP_SLOT_SZ >> 1) - 1; 2165b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->sas.lldd_ha = mvi; 2166b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->sas.core.shost = mvi->shost; 2167b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 21688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_tag_init(mvi); 2169b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2170b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* 2171b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * ioremap main and peripheral registers 2172b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 2173b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 21748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#ifdef MVS_ENABLE_PERI 2175b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik res_start = pci_resource_start(pdev, 2); 2176b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik res_len = pci_resource_len(pdev, 2); 2177b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!res_start || !res_len) 2178b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 2179b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2180b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->peri_regs = ioremap_nocache(res_start, res_len); 21818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (!mvi->peri_regs) 2182b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 21838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 2184b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2185b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik res_start = pci_resource_start(pdev, 4); 2186b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik res_len = pci_resource_len(pdev, 4); 2187b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!res_start || !res_len) 2188b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 2189b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 21908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei res_flag = pci_resource_flags(pdev, 4); 21918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (res_flag & IORESOURCE_CACHEABLE) 21928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->regs = ioremap(res_start, res_len); 21938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 21948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->regs = ioremap_nocache(res_start, res_len); 21958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 2196b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!mvi->regs) 2197b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 2198b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2199b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* 2200b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * alloc and init our DMA areas 2201b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 2202b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2203b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->tx = dma_alloc_coherent(&pdev->dev, 22048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ, 2205b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik &mvi->tx_dma, GFP_KERNEL); 2206b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!mvi->tx) 2207b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 22088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei memset(mvi->tx, 0, sizeof(*mvi->tx) * MVS_CHIP_SLOT_SZ); 2209b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2210b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->rx_fis = dma_alloc_coherent(&pdev->dev, MVS_RX_FISL_SZ, 22118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei &mvi->rx_fis_dma, GFP_KERNEL); 2212b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!mvi->rx_fis) 2213b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 2214b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik memset(mvi->rx_fis, 0, MVS_RX_FISL_SZ); 2215b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2216b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->rx = dma_alloc_coherent(&pdev->dev, 2217b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sizeof(*mvi->rx) * MVS_RX_RING_SZ, 2218b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik &mvi->rx_dma, GFP_KERNEL); 2219b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!mvi->rx) 2220b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 2221b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik memset(mvi->rx, 0, sizeof(*mvi->rx) * MVS_RX_RING_SZ); 2222b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2223b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->rx[0] = cpu_to_le32(0xfff); 2224b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->rx_cons = 0xfff; 2225b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2226b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->slot = dma_alloc_coherent(&pdev->dev, 2227b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sizeof(*mvi->slot) * MVS_SLOTS, 2228b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik &mvi->slot_dma, GFP_KERNEL); 2229b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!mvi->slot) 2230b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 2231b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik memset(mvi->slot, 0, sizeof(*mvi->slot) * MVS_SLOTS); 2232b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2233b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik for (i = 0; i < MVS_SLOTS; i++) { 2234b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_slot_info *slot = &mvi->slot_info[i]; 2235b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2236b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik slot->buf = dma_alloc_coherent(&pdev->dev, MVS_SLOT_BUF_SZ, 22378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei &slot->buf_dma, GFP_KERNEL); 2238b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!slot->buf) 2239b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 2240b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik memset(slot->buf, 0, MVS_SLOT_BUF_SZ); 2241b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 2242b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2243b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* finally, read NVRAM to get our SAS address */ 2244b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (mvs_nvram_read(mvi, NVR_SAS_ADDR, &mvi->sas_addr, 8)) 2245b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 2246b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return mvi; 2247b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2248b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out: 2249b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_free(mvi); 2250b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return NULL; 2251b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2252b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2253b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic u32 mvs_cr32(void __iomem *regs, u32 addr) 2254b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2255b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(CMD_ADDR, addr); 2256b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return mr32(CMD_DATA); 2257b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2258b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2259b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic void mvs_cw32(void __iomem *regs, u32 addr, u32 val) 2260b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2261b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(CMD_ADDR, addr); 2262b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(CMD_DATA, val); 2263b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2264b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 22658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_read_phy_ctl(struct mvs_info *mvi, u32 port) 2266b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2267b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void __iomem *regs = mvi->regs; 22688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return (port < 4)?mr32(P0_SER_CTLSTAT + port * 4): 22698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mr32(P4_SER_CTLSTAT + (port - 4) * 4); 2270b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2271b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 22728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_phy_ctl(struct mvs_info *mvi, u32 port, u32 val) 2273b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2274b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void __iomem *regs = mvi->regs; 22758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (port < 4) 22768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(P0_SER_CTLSTAT + port * 4, val); 22778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 22788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(P4_SER_CTLSTAT + (port - 4) * 4, val); 22798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 22808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 22818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_read_port(struct mvs_info *mvi, u32 off, u32 off2, u32 port) 22828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 22838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs + off; 22848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs2 = mvi->regs + off2; 22858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return (port < 4)?readl(regs + port * 8): 22868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei readl(regs2 + (port - 4) * 8); 22878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 22888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 22898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port(struct mvs_info *mvi, u32 off, u32 off2, 22908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 port, u32 val) 22918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 22928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs + off; 22938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs2 = mvi->regs + off2; 22948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (port < 4) 22958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei writel(val, regs + port * 8); 22968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 22978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei writel(val, regs2 + (port - 4) * 8); 22988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 22998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 23008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_read_port_cfg_data(struct mvs_info *mvi, u32 port) 23018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 23028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return mvs_read_port(mvi, MVS_P0_CFG_DATA, MVS_P4_CFG_DATA, port); 23038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 23048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 23058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port_cfg_data(struct mvs_info *mvi, u32 port, u32 val) 23068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 23078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port(mvi, MVS_P0_CFG_DATA, MVS_P4_CFG_DATA, port, val); 23088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 23098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 23108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port_cfg_addr(struct mvs_info *mvi, u32 port, u32 addr) 23118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 23128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port(mvi, MVS_P0_CFG_ADDR, MVS_P4_CFG_ADDR, port, addr); 23138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 23148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 23158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_read_port_vsr_data(struct mvs_info *mvi, u32 port) 23168f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 23178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return mvs_read_port(mvi, MVS_P0_VSR_DATA, MVS_P4_VSR_DATA, port); 23188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 23198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 23208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port_vsr_data(struct mvs_info *mvi, u32 port, u32 val) 23218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 23228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port(mvi, MVS_P0_VSR_DATA, MVS_P4_VSR_DATA, port, val); 23238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 23248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 23258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port_vsr_addr(struct mvs_info *mvi, u32 port, u32 addr) 23268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 23278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port(mvi, MVS_P0_VSR_ADDR, MVS_P4_VSR_ADDR, port, addr); 23288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 23298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 23308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_read_port_irq_stat(struct mvs_info *mvi, u32 port) 23318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 23328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return mvs_read_port(mvi, MVS_P0_INT_STAT, MVS_P4_INT_STAT, port); 23338f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 23348f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 23358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port_irq_stat(struct mvs_info *mvi, u32 port, u32 val) 23368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 23378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port(mvi, MVS_P0_INT_STAT, MVS_P4_INT_STAT, port, val); 23388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 23398f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 23408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_read_port_irq_mask(struct mvs_info *mvi, u32 port) 23418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 23428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return mvs_read_port(mvi, MVS_P0_INT_MASK, MVS_P4_INT_MASK, port); 23438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 2344b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 23458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_write_port_irq_mask(struct mvs_info *mvi, u32 port, u32 val) 23468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 23478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port(mvi, MVS_P0_INT_MASK, MVS_P4_INT_MASK, port, val); 2348b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2349b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2350b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic void __devinit mvs_phy_hacks(struct mvs_info *mvi) 2351b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2352b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void __iomem *regs = mvi->regs; 2353b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u32 tmp; 2354b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2355b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* workaround for SATA R-ERR, to ignore phy glitch */ 2356b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp = mvs_cr32(regs, CMD_PHY_TIMER); 2357b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp &= ~(1 << 9); 2358b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp |= (1 << 10); 2359b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_cw32(regs, CMD_PHY_TIMER, tmp); 2360b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2361b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* enable retry 127 times */ 2362b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_cw32(regs, CMD_SAS_CTL1, 0x7f7f); 2363b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2364b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* extend open frame timeout to max */ 2365b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp = mvs_cr32(regs, CMD_SAS_CTL0); 2366b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp &= ~0xffff; 2367b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp |= 0x3fff; 2368b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_cw32(regs, CMD_SAS_CTL0, tmp); 2369b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2370b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* workaround for WDTIMEOUT , set to 550 ms */ 2371b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_cw32(regs, CMD_WD_TIMER, 0xffffff); 2372b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2373b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* not to halt for different port op during wideport link change */ 2374b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_cw32(regs, CMD_APP_ERR_CONFIG, 0xffefbf7d); 2375b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2376b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* workaround for Seagate disk not-found OOB sequence, recv 2377b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * COMINIT before sending out COMWAKE */ 2378b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp = mvs_cr32(regs, CMD_PHY_MODE_21); 2379b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp &= 0x0000ffff; 2380b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp |= 0x00fa0000; 2381b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_cw32(regs, CMD_PHY_MODE_21, tmp); 2382b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2383b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp = mvs_cr32(regs, CMD_PHY_TIMER); 2384b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp &= 0x1fffffff; 2385b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp |= (2U << 29); /* 8 ms retry */ 2386b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_cw32(regs, CMD_PHY_TIMER, tmp); 23878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 23888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* TEST - for phy decoding error, adjust voltage levels */ 23898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(P0_VSR_ADDR + 0, 0x8); 23908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(P0_VSR_DATA + 0, 0x2F0); 23918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 23928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(P0_VSR_ADDR + 8, 0x8); 23938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(P0_VSR_DATA + 8, 0x2F0); 23948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 23958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(P0_VSR_ADDR + 16, 0x8); 23968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(P0_VSR_DATA + 16, 0x2F0); 23978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 23988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(P0_VSR_ADDR + 24, 0x8); 23998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(P0_VSR_DATA + 24, 0x2F0); 24008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 24028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_enable_xmt(struct mvs_info *mvi, int PhyId) 24048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 24058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs; 24068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tmp; 24078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mr32(PCS); 24098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (mvi->chip->n_phy <= 4) 24108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp |= 1 << (PhyId + PCS_EN_PORT_XMT_SHIFT); 24118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 24128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp |= 1 << (PhyId + PCS_EN_PORT_XMT_SHIFT2); 24138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(PCS, tmp); 24148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 24158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24168f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_detect_porttype(struct mvs_info *mvi, int i) 24178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 24188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs; 24198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 reg; 24208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_phy *phy = &mvi->phy[i]; 24218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* TODO check & save device type */ 24238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei reg = mr32(GBL_PORT_TYPE); 24248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (reg & MODE_SAS_SATA & (1 << i)) 24268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->phy_type |= PORT_TYPE_SAS; 24278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 24288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->phy_type |= PORT_TYPE_SATA; 24298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 24308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void *mvs_get_d2h_reg(struct mvs_info *mvi, int i, void *buf) 24328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 24338f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 *s = (u32 *) buf; 24348f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (!s) 24368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return NULL; 24378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, i, PHYR_SATA_SIG3); 24398f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei s[3] = mvs_read_port_cfg_data(mvi, i); 24408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, i, PHYR_SATA_SIG2); 24428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei s[2] = mvs_read_port_cfg_data(mvi, i); 24438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, i, PHYR_SATA_SIG1); 24458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei s[1] = mvs_read_port_cfg_data(mvi, i); 24468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, i, PHYR_SATA_SIG0); 24488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei s[0] = mvs_read_port_cfg_data(mvi, i); 24498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return (void *)s; 24518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 24528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_is_sig_fis_received(u32 irq_status) 24548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 24558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return irq_status & PHYEV_SIG_FIS; 24568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 24578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_update_wideport(struct mvs_info *mvi, int i) 24598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 24608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_phy *phy = &mvi->phy[i]; 24618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_port *port = phy->port; 24628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei int j, no; 24638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei for_each_phy(port->wide_port_phymap, no, j, mvi->chip->n_phy) 24658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (no & 1) { 24668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, no, PHYR_WIDE_PORT); 24678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_data(mvi, no, 24688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei port->wide_port_phymap); 24698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } else { 24708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, no, PHYR_WIDE_PORT); 24718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_data(mvi, no, 0); 24728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 24738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 24748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic u32 mvs_is_phy_ready(struct mvs_info *mvi, int i) 24768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 24778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tmp; 24788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_phy *phy = &mvi->phy[i]; 24798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_port *port; 24808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mvs_read_phy_ctl(mvi, i); 24828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if ((tmp & PHY_READY_MASK) && !(phy->irq_status & PHYEV_POOF)) { 24848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (!phy->port) 24858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->phy_attached = 1; 24868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return tmp; 24878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 24888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 24898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei port = phy->port; 24908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (port) { 24918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy->phy_type & PORT_TYPE_SAS) { 24928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei port->wide_port_phymap &= ~(1U << i); 24938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (!port->wide_port_phymap) 24948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei port->port_attached = 0; 24958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_update_wideport(mvi, i); 24968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } else if (phy->phy_type & PORT_TYPE_SATA) 24978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei port->port_attached = 0; 24988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_free_reg_set(mvi, phy->port); 24998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->port = NULL; 25008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->phy_attached = 0; 25018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA); 25028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 25038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return 0; 25048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 25058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_update_phyinfo(struct mvs_info *mvi, int i, 25078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei int get_st) 25088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 25098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_phy *phy = &mvi->phy[i]; 25108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct pci_dev *pdev = mvi->pdev; 25118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tmp, j; 25128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u64 tmp64; 25138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, i, PHYR_IDENTIFY); 25158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->dev_info = mvs_read_port_cfg_data(mvi, i); 25168f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, i, PHYR_ADDR_HI); 25188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->dev_sas_addr = (u64) mvs_read_port_cfg_data(mvi, i) << 32; 25198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, i, PHYR_ADDR_LO); 25218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->dev_sas_addr |= mvs_read_port_cfg_data(mvi, i); 25228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (get_st) { 25248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->irq_status = mvs_read_port_irq_stat(mvi, i); 25258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->phy_status = mvs_is_phy_ready(mvi, i); 25268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 25278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy->phy_status) { 25298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 phy_st; 25308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct asd_sas_phy *sas_phy = mvi->sas.sas_phy[i]; 25318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, i, PHYR_PHY_STAT); 25338f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy_st = mvs_read_port_cfg_data(mvi, i); 25348f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sas_phy->linkrate = 25368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >> 25378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET; 25388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25398f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* Updated attached_sas_addr */ 25408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_ADDR_HI); 25418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->att_dev_sas_addr = 25428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u64) mvs_read_port_cfg_data(mvi, i) << 32; 25438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_ADDR_LO); 25458f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->att_dev_sas_addr |= mvs_read_port_cfg_data(mvi, i); 25468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, 25488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "phy[%d] Get Attached Address 0x%llX ," 25498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei " SAS Address 0x%llX\n", 25508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei i, phy->att_dev_sas_addr, phy->dev_sas_addr); 25518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, 25528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "Rate = %x , type = %d\n", 25538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sas_phy->linkrate, phy->phy_type); 25548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#if 1 25568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* 25578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * If the device is capable of supporting a wide port 25588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * on its phys, it may configure the phys as a wide port. 25598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei */ 25608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy->phy_type & PORT_TYPE_SAS) 25618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei for (j = 0; j < mvi->chip->n_phy && j != i; ++j) { 25628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if ((mvi->phy[j].phy_attached) && 25638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (mvi->phy[j].phy_type & PORT_TYPE_SAS)) 25648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy->att_dev_sas_addr == 25658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->phy[j].att_dev_sas_addr - 1) { 25668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->att_dev_sas_addr = 25678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->phy[j].att_dev_sas_addr; 25688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei break; 25698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 25708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 25718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 25738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp64 = cpu_to_be64(phy->att_dev_sas_addr); 25758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei memcpy(sas_phy->attached_sas_addr, &tmp64, SAS_ADDR_SIZE); 25768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy->phy_type & PORT_TYPE_SAS) { 25788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, i, PHYR_ATT_DEV_INFO); 25798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->att_dev_info = mvs_read_port_cfg_data(mvi, i); 25808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->identify.device_type = 25818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->att_dev_info & PORT_DEV_TYPE_MASK; 25828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 25838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy->identify.device_type == SAS_END_DEV) 25848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->identify.target_port_protocols = 25858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei SAS_PROTOCOL_SSP; 25868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else if (phy->identify.device_type != NO_DEVICE) 25878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->identify.target_port_protocols = 25888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei SAS_PROTOCOL_SMP; 25898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy_st & PHY_OOB_DTCTD) 25908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sas_phy->oob_mode = SAS_OOB_MODE; 25918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->frame_rcvd_size = 25928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sizeof(struct sas_identify_frame); 25938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } else if (phy->phy_type & PORT_TYPE_SATA) { 25948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->identify.target_port_protocols = SAS_PROTOCOL_STP; 25958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (mvs_is_sig_fis_received(phy->irq_status)) { 25968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy_st & PHY_OOB_DTCTD) 25978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sas_phy->oob_mode = SATA_OOB_MODE; 25988f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->frame_rcvd_size = 25998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sizeof(struct dev_to_host_fis); 26008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_get_d2h_reg(mvi, i, 26018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (void *)sas_phy->frame_rcvd); 26028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } else { 26038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei dev_printk(KERN_DEBUG, &pdev->dev, 26048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "No sig fis\n"); 26058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 26068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 26078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* workaround for HW phy decoding error on 1.5g disk drive */ 26088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE6); 26098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mvs_read_port_vsr_data(mvi, i); 26108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (((phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >> 26118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET) == 26128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei SAS_LINK_RATE_1_5_GBPS) 26138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp &= ~PHY_MODE6_DTL_SPEED; 26148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 26158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp |= PHY_MODE6_DTL_SPEED; 26168f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_vsr_data(mvi, i, tmp); 26178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 26188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 26198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (get_st) 26208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_irq_stat(mvi, i, phy->irq_status); 26218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 26228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 26238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_port_formed(struct asd_sas_phy *sas_phy) 26248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 26258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct sas_ha_struct *sas_ha = sas_phy->ha; 26268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_info *mvi = sas_ha->lldd_ha; 26278f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct asd_sas_port *sas_port = sas_phy->port; 26288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_phy *phy = sas_phy->lldd_phy; 26298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_port *port = &mvi->port[sas_port->id]; 26308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei unsigned long flags; 26318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 26328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei spin_lock_irqsave(&mvi->lock, flags); 26338f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei port->port_attached = 1; 26348f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei phy->port = port; 26358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei port->taskfileset = MVS_ID_NOT_MAPPED; 26368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (phy->phy_type & PORT_TYPE_SAS) { 26378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei port->wide_port_phymap = sas_port->phy_mask; 26388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_update_wideport(mvi, sas_phy->id); 26398f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 26408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei spin_unlock_irqrestore(&mvi->lock, flags); 2641b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2642b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2643b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic int __devinit mvs_hw_init(struct mvs_info *mvi) 2644b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2645b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void __iomem *regs = mvi->regs; 2646b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik int i; 2647b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u32 tmp, cctl; 2648b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2649b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* make sure interrupts are masked immediately (paranoia) */ 2650b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(GBL_CTL, 0); 2651b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp = mr32(GBL_CTL); 2652b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 26538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* Reset Controller */ 2654b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!(tmp & HBA_RST)) { 2655b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (mvi->flags & MVF_PHY_PWR_FIX) { 2656b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &tmp); 2657b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp &= ~PCTL_PWR_ON; 2658b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp |= PCTL_OFF; 2659b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp); 2660b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2661b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &tmp); 2662b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp &= ~PCTL_PWR_ON; 2663b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp |= PCTL_OFF; 2664b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, tmp); 2665b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 2666b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2667b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* global reset, incl. COMRESET/H_RESET_N (self-clearing) */ 2668b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32_f(GBL_CTL, HBA_RST); 2669b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 2670b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2671b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* wait for reset to finish; timeout is just a guess */ 2672b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik i = 1000; 2673b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik while (i-- > 0) { 2674b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik msleep(10); 2675b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2676b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!(mr32(GBL_CTL) & HBA_RST)) 2677b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik break; 2678b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 2679b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (mr32(GBL_CTL) & HBA_RST) { 2680b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dev_printk(KERN_ERR, &mvi->pdev->dev, "HBA reset failed\n"); 2681b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return -EBUSY; 2682b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 2683b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 26848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* Init Chip */ 2685b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* make sure RST is set; HBA_RST /should/ have done that for us */ 2686b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik cctl = mr32(CTL); 2687b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (cctl & CCTL_RST) 2688b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik cctl &= ~CCTL_RST; 2689b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik else 2690b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32_f(CTL, cctl | CCTL_RST); 2691b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 26928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* write to device control _AND_ device status register? - A.C. */ 26938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei pci_read_config_dword(mvi->pdev, PCR_DEV_CTRL, &tmp); 26948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp &= ~PRD_REQ_MASK; 26958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp |= PRD_REQ_SIZE; 26968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei pci_write_config_dword(mvi->pdev, PCR_DEV_CTRL, tmp); 26978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 2698b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &tmp); 2699b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp |= PCTL_PWR_ON; 2700b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp &= ~PCTL_OFF; 2701b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp); 2702b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2703b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &tmp); 2704b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp |= PCTL_PWR_ON; 2705b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp &= ~PCTL_OFF; 2706b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, tmp); 2707b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2708b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32_f(CTL, cctl); 2709b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 27108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* reset control */ 27118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(PCS, 0); /*MVS_PCS */ 27128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 2713b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_phy_hacks(mvi); 2714b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2715b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(CMD_LIST_LO, mvi->slot_dma); 2716b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(CMD_LIST_HI, (mvi->slot_dma >> 16) >> 16); 2717b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2718b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(RX_FIS_LO, mvi->rx_fis_dma); 2719b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(RX_FIS_HI, (mvi->rx_fis_dma >> 16) >> 16); 2720b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 27218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(TX_CFG, MVS_CHIP_SLOT_SZ); 2722b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(TX_LO, mvi->tx_dma); 2723b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(TX_HI, (mvi->tx_dma >> 16) >> 16); 2724b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2725b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(RX_CFG, MVS_RX_RING_SZ); 2726b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(RX_LO, mvi->rx_dma); 2727b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(RX_HI, (mvi->rx_dma >> 16) >> 16); 2728b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 27298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* enable auto port detection */ 27308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(GBL_PORT_TYPE, MODE_AUTO_DET_EN); 27318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei msleep(100); 2732b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* init and reset phys */ 2733b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik for (i = 0; i < mvi->chip->n_phy; i++) { 2734b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* FIXME: is this the correct dword order? */ 27358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 lo = *((u32 *)&mvi->sas_addr[0]); 27368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 hi = *((u32 *)&mvi->sas_addr[4]); 27378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 27388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_detect_porttype(mvi, i); 2739b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2740b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* set phy local SAS address */ 27418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, i, PHYR_ADDR_LO); 27428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_data(mvi, i, lo); 27438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_addr(mvi, i, PHYR_ADDR_HI); 27448f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_cfg_data(mvi, i, hi); 2745b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2746b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* reset phy */ 27478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mvs_read_phy_ctl(mvi, i); 2748b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik tmp |= PHY_RST; 27498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_phy_ctl(mvi, i, tmp); 2750b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 2751b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2752b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik msleep(100); 2753b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2754b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik for (i = 0; i < mvi->chip->n_phy; i++) { 27558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* clear phy int status */ 27568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mvs_read_port_irq_stat(mvi, i); 27578f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp &= ~PHYEV_SIG_FIS; 27588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_irq_stat(mvi, i, tmp); 27598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 2760b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* set phy int mask */ 27618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = PHYEV_RDY_CH | PHYEV_BROAD_CH | PHYEV_UNASSOC_FIS | 27628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei PHYEV_ID_DONE | PHYEV_DEC_ERR; 27638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_write_port_irq_mask(mvi, i, tmp); 2764b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 27658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei msleep(100); 27668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_update_phyinfo(mvi, i, 1); 27678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_enable_xmt(mvi, i); 2768b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 2769b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2770b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* FIXME: update wide port bitmaps */ 2771b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 27728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* little endian for open address and command table, etc. */ 27738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* A.C. 27748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * it seems that ( from the spec ) turning on big-endian won't 27758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * do us any good on big-endian machines, need further confirmation 27768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei */ 27778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei cctl = mr32(CTL); 27788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei cctl |= CCTL_ENDIAN_CMD; 27798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei cctl |= CCTL_ENDIAN_DATA; 27808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei cctl &= ~CCTL_ENDIAN_OPEN; 27818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei cctl |= CCTL_ENDIAN_RSP; 27828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32_f(CTL, cctl); 27838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 27848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* reset CMD queue */ 27858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mr32(PCS); 27868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp |= PCS_CMD_RST; 27878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(PCS, tmp); 27888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* interrupt coalescing may cause missing HW interrput in some case, 27898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * and the max count is 0x1ff, while our max slot is 0x200, 27908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei * it will make count 0. 27918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei */ 27928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = 0; 27938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(INT_COAL, tmp); 27948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 27958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = 0x100; 27968f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(INT_COAL_TMOUT, tmp); 27978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 2798b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* ladies and gentlemen, start your engines */ 27998f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(TX_CFG, 0); 28008f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(TX_CFG, MVS_CHIP_SLOT_SZ | TX_EN); 2801b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mw32(RX_CFG, MVS_RX_RING_SZ | RX_EN); 28028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* enable CMD/CMPL_Q/RESP mode */ 28038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(PCS, PCS_SATA_RETRY | PCS_FIS_RX_EN | PCS_CMD_EN); 2804b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2805b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* re-enable interrupts globally */ 28068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hba_interrupt_enable(mvi); 28078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 28088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* enable completion queue interrupt */ 28098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM); 28108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(INT_MASK, tmp); 2811b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2812b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return 0; 2813b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2814b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2815b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic void __devinit mvs_print_info(struct mvs_info *mvi) 2816b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2817b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct pci_dev *pdev = mvi->pdev; 2818b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik static int printed_version; 2819b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2820b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!printed_version++) 2821b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dev_printk(KERN_INFO, &pdev->dev, "version " DRV_VERSION "\n"); 2822b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2823b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dev_printk(KERN_INFO, &pdev->dev, "%u phys, addr %llx\n", 2824b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->chip->n_phy, SAS_ADDR(mvi->sas_addr)); 2825b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2826b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2827b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic int __devinit mvs_pci_init(struct pci_dev *pdev, 28288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei const struct pci_device_id *ent) 2829b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2830b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik int rc; 2831b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_info *mvi; 2832b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik irq_handler_t irq_handler = mvs_interrupt; 2833b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2834b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = pci_enable_device(pdev); 2835b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) 2836b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 2837b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2838b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_set_master(pdev); 2839b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2840b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = pci_request_regions(pdev, DRV_NAME); 2841b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) 2842b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out_disable; 2843b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2844b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = pci_go_64(pdev); 2845b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) 2846b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out_regions; 2847b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2848b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi = mvs_alloc(pdev, ent); 2849b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!mvi) { 2850b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = -ENOMEM; 2851b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out_regions; 2852b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 2853b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2854b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = mvs_hw_init(mvi); 2855b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) 2856b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out_mvi; 2857b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 28588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#ifndef MVS_DISABLE_MSI 2859b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!pci_enable_msi(pdev)) { 28608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tmp; 28618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs; 2862b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvi->flags |= MVF_MSI; 2863b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik irq_handler = mvs_msi_interrupt; 28648f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tmp = mr32(PCS); 28658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mw32(PCS, tmp | PCS_SELF_CLEAR); 2866b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 28678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 2868b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2869b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = request_irq(pdev->irq, irq_handler, IRQF_SHARED, DRV_NAME, mvi); 2870b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) 2871b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out_msi; 2872b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2873b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = scsi_add_host(mvi->shost, &pdev->dev); 2874b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) 2875b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out_irq; 2876b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2877b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = sas_register_ha(&mvi->sas); 2878b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) 2879b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out_shost; 2880b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2881b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_set_drvdata(pdev, mvi); 2882b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2883b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_print_info(mvi); 2884b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2885b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik scsi_scan_host(mvi->shost); 28868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 2887b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return 0; 2888b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2889b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out_shost: 2890b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik scsi_remove_host(mvi->shost); 2891b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out_irq: 2892b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik free_irq(pdev->irq, mvi); 2893b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out_msi: 2894b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (mvi->flags |= MVF_MSI) 2895b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_disable_msi(pdev); 2896b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out_mvi: 2897b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_free(mvi); 2898b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out_regions: 2899b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_release_regions(pdev); 2900b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out_disable: 2901b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_disable_device(pdev); 2902b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 2903b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2904b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2905b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic void __devexit mvs_pci_remove(struct pci_dev *pdev) 2906b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2907b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_info *mvi = pci_get_drvdata(pdev); 2908b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2909b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_set_drvdata(pdev, NULL); 2910b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 29118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (mvi) { 29128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sas_unregister_ha(&mvi->sas); 29138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hba_interrupt_disable(mvi); 29148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sas_remove_host(mvi->shost); 29158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei scsi_remove_host(mvi->shost); 29168f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 29178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei free_irq(pdev->irq, mvi); 29188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (mvi->flags & MVF_MSI) 29198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei pci_disable_msi(pdev); 29208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_free(mvi); 29218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei pci_release_regions(pdev); 29228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 2923b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_disable_device(pdev); 2924b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2925b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2926b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic struct sas_domain_function_template mvs_transport_ops = { 2927b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .lldd_execute_task = mvs_task_exec, 2928b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .lldd_control_phy = mvs_phy_control, 29298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei .lldd_abort_task = mvs_task_abort, 29308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei .lldd_port_formed = mvs_port_formed 2931b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 2932b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2933b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic struct pci_device_id __devinitdata mvs_pci_table[] = { 2934b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik { PCI_VDEVICE(MARVELL, 0x6320), chip_6320 }, 2935b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik { PCI_VDEVICE(MARVELL, 0x6340), chip_6440 }, 2936b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik { PCI_VDEVICE(MARVELL, 0x6440), chip_6440 }, 2937b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik { PCI_VDEVICE(MARVELL, 0x6480), chip_6480 }, 2938b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2939b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik { } /* terminate list */ 2940b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 2941b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2942b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic struct pci_driver mvs_pci_driver = { 2943b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .name = DRV_NAME, 2944b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .id_table = mvs_pci_table, 2945b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .probe = mvs_pci_init, 2946b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik .remove = __devexit_p(mvs_pci_remove), 2947b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik}; 2948b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2949b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic int __init mvs_init(void) 2950b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2951b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik int rc; 2952b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2953b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik mvs_stt = sas_domain_attach_transport(&mvs_transport_ops); 2954b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (!mvs_stt) 2955b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return -ENOMEM; 2956b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2957b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik rc = pci_register_driver(&mvs_pci_driver); 2958b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (rc) 2959b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik goto err_out; 2960b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2961b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return 0; 2962b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2963b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out: 2964b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_release_transport(mvs_stt); 2965b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 2966b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2967b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2968b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic void __exit mvs_exit(void) 2969b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 2970b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik pci_unregister_driver(&mvs_pci_driver); 2971b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik sas_release_transport(mvs_stt); 2972b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2973b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2974b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikmodule_init(mvs_init); 2975b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikmodule_exit(mvs_exit); 2976b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2977b5762948263dd5e9725a380e7a9626f99e40ae9dJeff GarzikMODULE_AUTHOR("Jeff Garzik <jgarzik@pobox.com>"); 2978b5762948263dd5e9725a380e7a9626f99e40ae9dJeff GarzikMODULE_DESCRIPTION("Marvell 88SE6440 SAS/SATA controller driver"); 2979b5762948263dd5e9725a380e7a9626f99e40ae9dJeff GarzikMODULE_VERSION(DRV_VERSION); 2980b5762948263dd5e9725a380e7a9626f99e40ae9dJeff GarzikMODULE_LICENSE("GPL"); 2981b5762948263dd5e9725a380e7a9626f99e40ae9dJeff GarzikMODULE_DEVICE_TABLE(pci, mvs_pci_table); 2982