Author: maks Date: Fri Feb 1 14:58:28 2008 New Revision: 10363 Log: [scsi] update hptiop driver to sid etch+half tree
patch taken from latest linus so no need to apply to trunk. hptiop asks nicely to have that shipped in etch too. Added: dists/sid/linux-2.6/debian/patches/features/all/hptiop-update.patch dists/sid/linux-2.6/debian/patches/series/3 Modified: dists/sid/linux-2.6/debian/changelog Modified: dists/sid/linux-2.6/debian/changelog ============================================================================== --- dists/sid/linux-2.6/debian/changelog (original) +++ dists/sid/linux-2.6/debian/changelog Fri Feb 1 14:58:28 2008 @@ -1,3 +1,9 @@ +linux-2.6 (2.6.24-3) unstable; urgency=low + + * [scsi]: hptiop: add more adapter models and fixes. + + -- maximilian attems <[EMAIL PROTECTED]> Fri, 01 Feb 2008 15:53:59 +0100 + linux-2.6 (2.6.24-2) unstable; urgency=low [ Bastian Blank ] Added: dists/sid/linux-2.6/debian/patches/features/all/hptiop-update.patch ============================================================================== --- (empty file) +++ dists/sid/linux-2.6/debian/patches/features/all/hptiop-update.patch Fri Feb 1 14:58:28 2008 @@ -0,0 +1,1308 @@ +From: HighPoint Linux Team <[EMAIL PROTECTED]> +Date: Fri, 14 Dec 2007 00:14:26 +0000 (-0800) +Subject: [SCSI] hptiop: add more adapter models and other fixes +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=00f5970193e22c48f399a2430635d6416b51befe + +[SCSI] hptiop: add more adapter models and other fixes + +Most code changes were made to support adapters based on Marvell IOP, plus some +other fixes. + +- add more PCI device IDs +- support for adapters based on Marvell IOP +- fix a result code translation error on big-endian systems +- fix resource releasing bug when scsi_host_alloc() fail in hptiop_probe() +- update scsi_cmnd.resid when finishing a request +- correct some coding style issues + [EMAIL PROTECTED]: type fixes] +Signed-off-by: HighPoint Linux Team <[EMAIL PROTECTED]> +Signed-off-by: Andrew Morton <[EMAIL PROTECTED]> +Signed-off-by: James Bottomley <[EMAIL PROTECTED]> +--- + +diff --git a/Documentation/scsi/hptiop.txt b/Documentation/scsi/hptiop.txt +index d28a312..a6eb4ad 100644 +--- a/Documentation/scsi/hptiop.txt ++++ b/Documentation/scsi/hptiop.txt +@@ -1,9 +1,9 @@ +-HIGHPOINT ROCKETRAID 3xxx RAID DRIVER (hptiop) ++HIGHPOINT ROCKETRAID 3xxx/4xxx ADAPTER DRIVER (hptiop) + + Controller Register Map + ------------------------- + +-The controller IOP is accessed via PCI BAR0. ++For Intel IOP based adapters, the controller IOP is accessed via PCI BAR0: + + BAR0 offset Register + 0x10 Inbound Message Register 0 +@@ -18,6 +18,24 @@ The controller IOP is accessed via PCI BAR0. + 0x40 Inbound Queue Port + 0x44 Outbound Queue Port + ++For Marvell IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1: ++ ++ BAR0 offset Register ++ 0x20400 Inbound Doorbell Register ++ 0x20404 Inbound Interrupt Mask Register ++ 0x20408 Outbound Doorbell Register ++ 0x2040C Outbound Interrupt Mask Register ++ ++ BAR1 offset Register ++ 0x0 Inbound Queue Head Pointer ++ 0x4 Inbound Queue Tail Pointer ++ 0x8 Outbound Queue Head Pointer ++ 0xC Outbound Queue Tail Pointer ++ 0x10 Inbound Message Register ++ 0x14 Outbound Message Register ++ 0x40-0x1040 Inbound Queue ++ 0x1040-0x2040 Outbound Queue ++ + + I/O Request Workflow + ---------------------- +@@ -73,15 +91,9 @@ The driver exposes following sysfs attributes: + driver-version R driver version string + firmware-version R firmware version string + +-The driver registers char device "hptiop" to communicate with HighPoint RAID +-management software. Its ioctl routine acts as a general binary interface +-between the IOP firmware and HighPoint RAID management software. New management +-functions can be implemented in application/firmware without modification +-in driver code. +- + + ----------------------------------------------------------------------------- +-Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved. ++Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved. + + This file is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of +diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig +index becbb09..e397599 100644 +--- a/drivers/scsi/Kconfig ++++ b/drivers/scsi/Kconfig +@@ -573,10 +573,10 @@ config SCSI_ARCMSR_AER + source "drivers/scsi/megaraid/Kconfig.megaraid" + + config SCSI_HPTIOP +- tristate "HighPoint RocketRAID 3xxx Controller support" ++ tristate "HighPoint RocketRAID 3xxx/4xxx Controller support" + depends on SCSI && PCI + help +- This option enables support for HighPoint RocketRAID 3xxx ++ This option enables support for HighPoint RocketRAID 3xxx/4xxx + controllers. + + To compile this driver as a module, choose M here; the module +diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c +index 0844331..df1a764 100644 +--- a/drivers/scsi/hptiop.c ++++ b/drivers/scsi/hptiop.c +@@ -1,5 +1,5 @@ + /* +- * HighPoint RR3xxx controller driver for Linux ++ * HighPoint RR3xxx/4xxx controller driver for Linux + * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify +@@ -38,80 +38,84 @@ + #include "hptiop.h" + + MODULE_AUTHOR("HighPoint Technologies, Inc."); +-MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx SATA Controller Driver"); ++MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx/4xxx Controller Driver"); + + static char driver_name[] = "hptiop"; +-static const char driver_name_long[] = "RocketRAID 3xxx SATA Controller driver"; +-static const char driver_ver[] = "v1.2 (070830)"; +- +-static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag); +-static void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag); ++static const char driver_name_long[] = "RocketRAID 3xxx/4xxx Controller driver"; ++static const char driver_ver[] = "v1.3 (071203)"; ++ ++static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec); ++static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag, ++ struct hpt_iop_request_scsi_command *req); ++static void hptiop_host_request_callback_itl(struct hptiop_hba *hba, u32 tag); ++static void hptiop_iop_request_callback_itl(struct hptiop_hba *hba, u32 tag); + static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg); + +-static inline void hptiop_pci_posting_flush(struct hpt_iopmu __iomem *iop) +-{ +- readl(&iop->outbound_intstatus); +-} +- +-static int iop_wait_ready(struct hpt_iopmu __iomem *iop, u32 millisec) ++static int iop_wait_ready_itl(struct hptiop_hba *hba, u32 millisec) + { + u32 req = 0; + int i; + + for (i = 0; i < millisec; i++) { +- req = readl(&iop->inbound_queue); ++ req = readl(&hba->u.itl.iop->inbound_queue); + if (req != IOPMU_QUEUE_EMPTY) + break; + msleep(1); + } + + if (req != IOPMU_QUEUE_EMPTY) { +- writel(req, &iop->outbound_queue); +- hptiop_pci_posting_flush(iop); ++ writel(req, &hba->u.itl.iop->outbound_queue); ++ readl(&hba->u.itl.iop->outbound_intstatus); + return 0; + } + + return -1; + } + +-static void hptiop_request_callback(struct hptiop_hba *hba, u32 tag) ++static int iop_wait_ready_mv(struct hptiop_hba *hba, u32 millisec) ++{ ++ return iop_send_sync_msg(hba, IOPMU_INBOUND_MSG0_NOP, millisec); ++} ++ ++static void hptiop_request_callback_itl(struct hptiop_hba *hba, u32 tag) + { + if (tag & IOPMU_QUEUE_ADDR_HOST_BIT) +- return hptiop_host_request_callback(hba, ++ hptiop_host_request_callback_itl(hba, + tag & ~IOPMU_QUEUE_ADDR_HOST_BIT); + else +- return hptiop_iop_request_callback(hba, tag); ++ hptiop_iop_request_callback_itl(hba, tag); + } + +-static inline void hptiop_drain_outbound_queue(struct hptiop_hba *hba) ++static void hptiop_drain_outbound_queue_itl(struct hptiop_hba *hba) + { + u32 req; + +- while ((req = readl(&hba->iop->outbound_queue)) != IOPMU_QUEUE_EMPTY) { ++ while ((req = readl(&hba->u.itl.iop->outbound_queue)) != ++ IOPMU_QUEUE_EMPTY) { + + if (req & IOPMU_QUEUE_MASK_HOST_BITS) +- hptiop_request_callback(hba, req); ++ hptiop_request_callback_itl(hba, req); + else { + struct hpt_iop_request_header __iomem * p; + + p = (struct hpt_iop_request_header __iomem *) +- ((char __iomem *)hba->iop + req); ++ ((char __iomem *)hba->u.itl.iop + req); + + if (readl(&p->flags) & IOP_REQUEST_FLAG_SYNC_REQUEST) { + if (readl(&p->context)) +- hptiop_request_callback(hba, req); ++ hptiop_request_callback_itl(hba, req); + else + writel(1, &p->context); + } + else +- hptiop_request_callback(hba, req); ++ hptiop_request_callback_itl(hba, req); + } + } + } + +-static int __iop_intr(struct hptiop_hba *hba) ++static int iop_intr_itl(struct hptiop_hba *hba) + { +- struct hpt_iopmu __iomem *iop = hba->iop; ++ struct hpt_iopmu_itl __iomem *iop = hba->u.itl.iop; + u32 status; + int ret = 0; + +@@ -119,6 +123,7 @@ static int __iop_intr(struct hptiop_hba *hba) + + if (status & IOPMU_OUTBOUND_INT_MSG0) { + u32 msg = readl(&iop->outbound_msgaddr0); ++ + dprintk("received outbound msg %x\n", msg); + writel(IOPMU_OUTBOUND_INT_MSG0, &iop->outbound_intstatus); + hptiop_message_callback(hba, msg); +@@ -126,31 +131,115 @@ static int __iop_intr(struct hptiop_hba *hba) + } + + if (status & IOPMU_OUTBOUND_INT_POSTQUEUE) { +- hptiop_drain_outbound_queue(hba); ++ hptiop_drain_outbound_queue_itl(hba); ++ ret = 1; ++ } ++ ++ return ret; ++} ++ ++static u64 mv_outbound_read(struct hpt_iopmu_mv __iomem *mu) ++{ ++ u32 outbound_tail = readl(&mu->outbound_tail); ++ u32 outbound_head = readl(&mu->outbound_head); ++ ++ if (outbound_tail != outbound_head) { ++ u64 p; ++ ++ memcpy_fromio(&p, &mu->outbound_q[mu->outbound_tail], 8); ++ outbound_tail++; ++ ++ if (outbound_tail == MVIOP_QUEUE_LEN) ++ outbound_tail = 0; ++ writel(outbound_tail, &mu->outbound_tail); ++ return p; ++ } else ++ return 0; ++} ++ ++static void mv_inbound_write(u64 p, struct hptiop_hba *hba) ++{ ++ u32 inbound_head = readl(&hba->u.mv.mu->inbound_head); ++ u32 head = inbound_head + 1; ++ ++ if (head == MVIOP_QUEUE_LEN) ++ head = 0; ++ ++ memcpy_toio(&hba->u.mv.mu->inbound_q[inbound_head], &p, 8); ++ writel(head, &hba->u.mv.mu->inbound_head); ++ writel(MVIOP_MU_INBOUND_INT_POSTQUEUE, ++ &hba->u.mv.regs->inbound_doorbell); ++} ++ ++static void hptiop_request_callback_mv(struct hptiop_hba *hba, u64 tag) ++{ ++ u32 req_type = (tag >> 5) & 0x7; ++ struct hpt_iop_request_scsi_command *req; ++ ++ dprintk("hptiop_request_callback_mv: tag=%llx\n", tag); ++ ++ BUG_ON((tag & MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT) == 0); ++ ++ switch (req_type) { ++ case IOP_REQUEST_TYPE_GET_CONFIG: ++ case IOP_REQUEST_TYPE_SET_CONFIG: ++ hba->msg_done = 1; ++ break; ++ ++ case IOP_REQUEST_TYPE_SCSI_COMMAND: ++ req = hba->reqs[tag >> 8].req_virt; ++ if (likely(tag & MVIOP_MU_QUEUE_REQUEST_RESULT_BIT)) ++ req->header.result = cpu_to_le32(IOP_RESULT_SUCCESS); ++ ++ hptiop_finish_scsi_req(hba, tag>>8, req); ++ break; ++ ++ default: ++ break; ++ } ++} ++ ++static int iop_intr_mv(struct hptiop_hba *hba) ++{ ++ u32 status; ++ int ret = 0; ++ ++ status = readl(&hba->u.mv.regs->outbound_doorbell); ++ writel(~status, &hba->u.mv.regs->outbound_doorbell); ++ ++ if (status & MVIOP_MU_OUTBOUND_INT_MSG) { ++ u32 msg; ++ msg = readl(&hba->u.mv.mu->outbound_msg); ++ dprintk("received outbound msg %x\n", msg); ++ hptiop_message_callback(hba, msg); ++ ret = 1; ++ } ++ ++ if (status & MVIOP_MU_OUTBOUND_INT_POSTQUEUE) { ++ u64 tag; ++ ++ while ((tag = mv_outbound_read(hba->u.mv.mu))) ++ hptiop_request_callback_mv(hba, tag); + ret = 1; + } + + return ret; + } + +-static int iop_send_sync_request(struct hptiop_hba *hba, ++static int iop_send_sync_request_itl(struct hptiop_hba *hba, + void __iomem *_req, u32 millisec) + { + struct hpt_iop_request_header __iomem *req = _req; + u32 i; + +- writel(readl(&req->flags) | IOP_REQUEST_FLAG_SYNC_REQUEST, +- &req->flags); +- ++ writel(readl(&req->flags) | IOP_REQUEST_FLAG_SYNC_REQUEST, &req->flags); + writel(0, &req->context); +- +- writel((unsigned long)req - (unsigned long)hba->iop, +- &hba->iop->inbound_queue); +- +- hptiop_pci_posting_flush(hba->iop); ++ writel((unsigned long)req - (unsigned long)hba->u.itl.iop, ++ &hba->u.itl.iop->inbound_queue); ++ readl(&hba->u.itl.iop->outbound_intstatus); + + for (i = 0; i < millisec; i++) { +- __iop_intr(hba); ++ iop_intr_itl(hba); + if (readl(&req->context)) + return 0; + msleep(1); +@@ -159,19 +248,49 @@ static int iop_send_sync_request(struct hptiop_hba *hba, + return -1; + } + +-static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec) ++static int iop_send_sync_request_mv(struct hptiop_hba *hba, ++ u32 size_bits, u32 millisec) + { ++ struct hpt_iop_request_header *reqhdr = hba->u.mv.internal_req; + u32 i; + + hba->msg_done = 0; ++ reqhdr->flags |= cpu_to_le32(IOP_REQUEST_FLAG_SYNC_REQUEST); ++ mv_inbound_write(hba->u.mv.internal_req_phy | ++ MVIOP_MU_QUEUE_ADDR_HOST_BIT | size_bits, hba); ++ ++ for (i = 0; i < millisec; i++) { ++ iop_intr_mv(hba); ++ if (hba->msg_done) ++ return 0; ++ msleep(1); ++ } ++ return -1; ++} ++ ++static void hptiop_post_msg_itl(struct hptiop_hba *hba, u32 msg) ++{ ++ writel(msg, &hba->u.itl.iop->inbound_msgaddr0); ++ readl(&hba->u.itl.iop->outbound_intstatus); ++} ++ ++static void hptiop_post_msg_mv(struct hptiop_hba *hba, u32 msg) ++{ ++ writel(msg, &hba->u.mv.mu->inbound_msg); ++ writel(MVIOP_MU_INBOUND_INT_MSG, &hba->u.mv.regs->inbound_doorbell); ++ readl(&hba->u.mv.regs->inbound_doorbell); ++} + +- writel(msg, &hba->iop->inbound_msgaddr0); ++static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec) ++{ ++ u32 i; + +- hptiop_pci_posting_flush(hba->iop); ++ hba->msg_done = 0; ++ hba->ops->post_msg(hba, msg); + + for (i = 0; i < millisec; i++) { + spin_lock_irq(hba->host->host_lock); +- __iop_intr(hba); ++ hba->ops->iop_intr(hba); + spin_unlock_irq(hba->host->host_lock); + if (hba->msg_done) + break; +@@ -181,46 +300,67 @@ static int iop_send_sync_msg(struct hptiop_hba *hba, u32 msg, u32 millisec) + return hba->msg_done? 0 : -1; + } + +-static int iop_get_config(struct hptiop_hba *hba, ++static int iop_get_config_itl(struct hptiop_hba *hba, + struct hpt_iop_request_get_config *config) + { + u32 req32; + struct hpt_iop_request_get_config __iomem *req; + +- req32 = readl(&hba->iop->inbound_queue); ++ req32 = readl(&hba->u.itl.iop->inbound_queue); + if (req32 == IOPMU_QUEUE_EMPTY) + return -1; + + req = (struct hpt_iop_request_get_config __iomem *) +- ((unsigned long)hba->iop + req32); ++ ((unsigned long)hba->u.itl.iop + req32); + + writel(0, &req->header.flags); + writel(IOP_REQUEST_TYPE_GET_CONFIG, &req->header.type); + writel(sizeof(struct hpt_iop_request_get_config), &req->header.size); + writel(IOP_RESULT_PENDING, &req->header.result); + +- if (iop_send_sync_request(hba, req, 20000)) { ++ if (iop_send_sync_request_itl(hba, req, 20000)) { + dprintk("Get config send cmd failed\n"); + return -1; + } + + memcpy_fromio(config, req, sizeof(*config)); +- writel(req32, &hba->iop->outbound_queue); ++ writel(req32, &hba->u.itl.iop->outbound_queue); ++ return 0; ++} ++ ++static int iop_get_config_mv(struct hptiop_hba *hba, ++ struct hpt_iop_request_get_config *config) ++{ ++ struct hpt_iop_request_get_config *req = hba->u.mv.internal_req; ++ ++ req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT); ++ req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_GET_CONFIG); ++ req->header.size = ++ cpu_to_le32(sizeof(struct hpt_iop_request_get_config)); ++ req->header.result = cpu_to_le32(IOP_RESULT_PENDING); ++ req->header.context = cpu_to_le64(IOP_REQUEST_TYPE_GET_CONFIG<<5); ++ ++ if (iop_send_sync_request_mv(hba, 0, 20000)) { ++ dprintk("Get config send cmd failed\n"); ++ return -1; ++ } ++ ++ memcpy(config, req, sizeof(struct hpt_iop_request_get_config)); + return 0; + } + +-static int iop_set_config(struct hptiop_hba *hba, ++static int iop_set_config_itl(struct hptiop_hba *hba, + struct hpt_iop_request_set_config *config) + { + u32 req32; + struct hpt_iop_request_set_config __iomem *req; + +- req32 = readl(&hba->iop->inbound_queue); ++ req32 = readl(&hba->u.itl.iop->inbound_queue); + if (req32 == IOPMU_QUEUE_EMPTY) + return -1; + + req = (struct hpt_iop_request_set_config __iomem *) +- ((unsigned long)hba->iop + req32); ++ ((unsigned long)hba->u.itl.iop + req32); + + memcpy_toio((u8 __iomem *)req + sizeof(struct hpt_iop_request_header), + (u8 *)config + sizeof(struct hpt_iop_request_header), +@@ -232,22 +372,52 @@ static int iop_set_config(struct hptiop_hba *hba, + writel(sizeof(struct hpt_iop_request_set_config), &req->header.size); + writel(IOP_RESULT_PENDING, &req->header.result); + +- if (iop_send_sync_request(hba, req, 20000)) { ++ if (iop_send_sync_request_itl(hba, req, 20000)) { + dprintk("Set config send cmd failed\n"); + return -1; + } + +- writel(req32, &hba->iop->outbound_queue); ++ writel(req32, &hba->u.itl.iop->outbound_queue); + return 0; + } + +-static int hptiop_initialize_iop(struct hptiop_hba *hba) ++static int iop_set_config_mv(struct hptiop_hba *hba, ++ struct hpt_iop_request_set_config *config) + { +- struct hpt_iopmu __iomem *iop = hba->iop; ++ struct hpt_iop_request_set_config *req = hba->u.mv.internal_req; + +- /* enable interrupts */ ++ memcpy(req, config, sizeof(struct hpt_iop_request_set_config)); ++ req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT); ++ req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SET_CONFIG); ++ req->header.size = ++ cpu_to_le32(sizeof(struct hpt_iop_request_set_config)); ++ req->header.result = cpu_to_le32(IOP_RESULT_PENDING); ++ req->header.context = cpu_to_le64(IOP_REQUEST_TYPE_SET_CONFIG<<5); ++ ++ if (iop_send_sync_request_mv(hba, 0, 20000)) { ++ dprintk("Set config send cmd failed\n"); ++ return -1; ++ } ++ ++ return 0; ++} ++ ++static void hptiop_enable_intr_itl(struct hptiop_hba *hba) ++{ + writel(~(IOPMU_OUTBOUND_INT_POSTQUEUE | IOPMU_OUTBOUND_INT_MSG0), +- &iop->outbound_intmask); ++ &hba->u.itl.iop->outbound_intmask); ++} ++ ++static void hptiop_enable_intr_mv(struct hptiop_hba *hba) ++{ ++ writel(MVIOP_MU_OUTBOUND_INT_POSTQUEUE | MVIOP_MU_OUTBOUND_INT_MSG, ++ &hba->u.mv.regs->outbound_intmask); ++} ++ ++static int hptiop_initialize_iop(struct hptiop_hba *hba) ++{ ++ /* enable interrupts */ ++ hba->ops->enable_intr(hba); + + hba->initialized = 1; + +@@ -261,37 +431,74 @@ static int hptiop_initialize_iop(struct hptiop_hba *hba) + return 0; + } + +-static int hptiop_map_pci_bar(struct hptiop_hba *hba) ++static void __iomem *hptiop_map_pci_bar(struct hptiop_hba *hba, int index) + { + u32 mem_base_phy, length; + void __iomem *mem_base_virt; ++ + struct pci_dev *pcidev = hba->pcidev; + +- if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) { ++ ++ if (!(pci_resource_flags(pcidev, index) & IORESOURCE_MEM)) { + printk(KERN_ERR "scsi%d: pci resource invalid\n", + hba->host->host_no); +- return -1; ++ return 0; + } + +- mem_base_phy = pci_resource_start(pcidev, 0); +- length = pci_resource_len(pcidev, 0); ++ mem_base_phy = pci_resource_start(pcidev, index); ++ length = pci_resource_len(pcidev, index); + mem_base_virt = ioremap(mem_base_phy, length); + + if (!mem_base_virt) { + printk(KERN_ERR "scsi%d: Fail to ioremap memory space\n", + hba->host->host_no); ++ return 0; ++ } ++ return mem_base_virt; ++} ++ ++static int hptiop_map_pci_bar_itl(struct hptiop_hba *hba) ++{ ++ hba->u.itl.iop = hptiop_map_pci_bar(hba, 0); ++ if (hba->u.itl.iop) ++ return 0; ++ else ++ return -1; ++} ++ ++static void hptiop_unmap_pci_bar_itl(struct hptiop_hba *hba) ++{ ++ iounmap(hba->u.itl.iop); ++} ++ ++static int hptiop_map_pci_bar_mv(struct hptiop_hba *hba) ++{ ++ hba->u.mv.regs = hptiop_map_pci_bar(hba, 0); ++ if (hba->u.mv.regs == 0) ++ return -1; ++ ++ hba->u.mv.mu = hptiop_map_pci_bar(hba, 2); ++ if (hba->u.mv.mu == 0) { ++ iounmap(hba->u.mv.regs); + return -1; + } + +- hba->iop = mem_base_virt; +- dprintk("hptiop_map_pci_bar: iop=%p\n", hba->iop); + return 0; + } + ++static void hptiop_unmap_pci_bar_mv(struct hptiop_hba *hba) ++{ ++ iounmap(hba->u.mv.regs); ++ iounmap(hba->u.mv.mu); ++} ++ + static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg) + { + dprintk("iop message 0x%x\n", msg); + ++ if (msg == IOPMU_INBOUND_MSG0_NOP) ++ hba->msg_done = 1; ++ + if (!hba->initialized) + return; + +@@ -303,7 +510,7 @@ static void hptiop_message_callback(struct hptiop_hba *hba, u32 msg) + hba->msg_done = 1; + } + +-static inline struct hptiop_request *get_req(struct hptiop_hba *hba) ++static struct hptiop_request *get_req(struct hptiop_hba *hba) + { + struct hptiop_request *ret; + +@@ -316,30 +523,19 @@ static inline struct hptiop_request *get_req(struct hptiop_hba *hba) + return ret; + } + +-static inline void free_req(struct hptiop_hba *hba, struct hptiop_request *req) ++static void free_req(struct hptiop_hba *hba, struct hptiop_request *req) + { + dprintk("free_req(%d, %p)\n", req->index, req); + req->next = hba->req_list; + hba->req_list = req; + } + +-static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 _tag) ++static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag, ++ struct hpt_iop_request_scsi_command *req) + { +- struct hpt_iop_request_scsi_command *req; + struct scsi_cmnd *scp; +- u32 tag; +- +- if (hba->iopintf_v2) { +- tag = _tag & ~ IOPMU_QUEUE_REQUEST_RESULT_BIT; +- req = hba->reqs[tag].req_virt; +- if (likely(_tag & IOPMU_QUEUE_REQUEST_RESULT_BIT)) +- req->header.result = IOP_RESULT_SUCCESS; +- } else { +- tag = _tag; +- req = hba->reqs[tag].req_virt; +- } + +- dprintk("hptiop_host_request_callback: req=%p, type=%d, " ++ dprintk("hptiop_finish_scsi_req: req=%p, type=%d, " + "result=%d, context=0x%x tag=%d\n", + req, req->header.type, req->header.result, + req->header.context, tag); +@@ -354,6 +550,8 @@ static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 _tag) + + switch (le32_to_cpu(req->header.result)) { + case IOP_RESULT_SUCCESS: ++ scsi_set_resid(scp, ++ scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length)); + scp->result = (DID_OK<<16); + break; + case IOP_RESULT_BAD_TARGET: +@@ -371,12 +569,12 @@ static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 _tag) + case IOP_RESULT_INVALID_REQUEST: + scp->result = (DID_ABORT<<16); + break; +- case IOP_RESULT_MODE_SENSE_CHECK_CONDITION: ++ case IOP_RESULT_CHECK_CONDITION: ++ scsi_set_resid(scp, ++ scsi_bufflen(scp) - le32_to_cpu(req->dataxfer_length)); + scp->result = SAM_STAT_CHECK_CONDITION; +- memset(&scp->sense_buffer, +- 0, sizeof(scp->sense_buffer)); + memcpy(&scp->sense_buffer, &req->sg_list, +- min(sizeof(scp->sense_buffer), ++ min_t(size_t, sizeof(scp->sense_buffer), + le32_to_cpu(req->dataxfer_length))); + break; + +@@ -391,15 +589,33 @@ static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 _tag) + free_req(hba, &hba->reqs[tag]); + } + +-void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag) ++static void hptiop_host_request_callback_itl(struct hptiop_hba *hba, u32 _tag) ++{ ++ struct hpt_iop_request_scsi_command *req; ++ u32 tag; ++ ++ if (hba->iopintf_v2) { ++ tag = _tag & ~IOPMU_QUEUE_REQUEST_RESULT_BIT; ++ req = hba->reqs[tag].req_virt; ++ if (likely(_tag & IOPMU_QUEUE_REQUEST_RESULT_BIT)) ++ req->header.result = cpu_to_le32(IOP_RESULT_SUCCESS); ++ } else { ++ tag = _tag; ++ req = hba->reqs[tag].req_virt; ++ } ++ ++ hptiop_finish_scsi_req(hba, tag, req); ++} ++ ++void hptiop_iop_request_callback_itl(struct hptiop_hba *hba, u32 tag) + { + struct hpt_iop_request_header __iomem *req; + struct hpt_iop_request_ioctl_command __iomem *p; + struct hpt_ioctl_k *arg; + + req = (struct hpt_iop_request_header __iomem *) +- ((unsigned long)hba->iop + tag); +- dprintk("hptiop_iop_request_callback: req=%p, type=%d, " ++ ((unsigned long)hba->u.itl.iop + tag); ++ dprintk("hptiop_iop_request_callback_itl: req=%p, type=%d, " + "result=%d, context=0x%x tag=%d\n", + req, readl(&req->type), readl(&req->result), + readl(&req->context), tag); +@@ -427,7 +643,7 @@ void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag) + arg->result = HPT_IOCTL_RESULT_FAILED; + + arg->done(arg); +- writel(tag, &hba->iop->outbound_queue); ++ writel(tag, &hba->u.itl.iop->outbound_queue); + } + + static irqreturn_t hptiop_intr(int irq, void *dev_id) +@@ -437,7 +653,7 @@ static irqreturn_t hptiop_intr(int irq, void *dev_id) + unsigned long flags; + + spin_lock_irqsave(hba->host->host_lock, flags); +- handled = __iop_intr(hba); ++ handled = hba->ops->iop_intr(hba); + spin_unlock_irqrestore(hba->host->host_lock, flags); + + return handled; +@@ -469,6 +685,57 @@ static int hptiop_buildsgl(struct scsi_cmnd *scp, struct hpt_iopsg *psg) + return HPT_SCP(scp)->sgcnt; + } + ++static void hptiop_post_req_itl(struct hptiop_hba *hba, ++ struct hptiop_request *_req) ++{ ++ struct hpt_iop_request_header *reqhdr = _req->req_virt; ++ ++ reqhdr->context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT | ++ (u32)_req->index); ++ reqhdr->context_hi32 = 0; ++ ++ if (hba->iopintf_v2) { ++ u32 size, size_bits; ++ ++ size = le32_to_cpu(reqhdr->size); ++ if (size < 256) ++ size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT; ++ else if (size < 512) ++ size_bits = IOPMU_QUEUE_ADDR_HOST_BIT; ++ else ++ size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT | ++ IOPMU_QUEUE_ADDR_HOST_BIT; ++ writel(_req->req_shifted_phy | size_bits, ++ &hba->u.itl.iop->inbound_queue); ++ } else ++ writel(_req->req_shifted_phy | IOPMU_QUEUE_ADDR_HOST_BIT, ++ &hba->u.itl.iop->inbound_queue); ++} ++ ++static void hptiop_post_req_mv(struct hptiop_hba *hba, ++ struct hptiop_request *_req) ++{ ++ struct hpt_iop_request_header *reqhdr = _req->req_virt; ++ u32 size, size_bit; ++ ++ reqhdr->context = cpu_to_le32(_req->index<<8 | ++ IOP_REQUEST_TYPE_SCSI_COMMAND<<5); ++ reqhdr->context_hi32 = 0; ++ size = le32_to_cpu(reqhdr->size); ++ ++ if (size <= 256) ++ size_bit = 0; ++ else if (size <= 256*2) ++ size_bit = 1; ++ else if (size <= 256*3) ++ size_bit = 2; ++ else ++ size_bit = 3; ++ ++ mv_inbound_write((_req->req_shifted_phy << 5) | ++ MVIOP_MU_QUEUE_ADDR_HOST_BIT | size_bit, hba); ++} ++ + static int hptiop_queuecommand(struct scsi_cmnd *scp, + void (*done)(struct scsi_cmnd *)) + { +@@ -518,9 +785,6 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, + req->header.flags = cpu_to_le32(IOP_REQUEST_FLAG_OUTPUT_CONTEXT); + req->header.type = cpu_to_le32(IOP_REQUEST_TYPE_SCSI_COMMAND); + req->header.result = cpu_to_le32(IOP_RESULT_PENDING); +- req->header.context = cpu_to_le32(IOPMU_QUEUE_ADDR_HOST_BIT | +- (u32)_req->index); +- req->header.context_hi32 = 0; + req->dataxfer_length = cpu_to_le32(scsi_bufflen(scp)); + req->channel = scp->device->channel; + req->target = scp->device->id; +@@ -531,21 +795,7 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, + + sg_count * sizeof(struct hpt_iopsg)); + + memcpy(req->cdb, scp->cmnd, sizeof(req->cdb)); +- +- if (hba->iopintf_v2) { +- u32 size_bits; +- if (req->header.size < 256) +- size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT; +- else if (req->header.size < 512) +- size_bits = IOPMU_QUEUE_ADDR_HOST_BIT; +- else +- size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT | +- IOPMU_QUEUE_ADDR_HOST_BIT; +- writel(_req->req_shifted_phy | size_bits, &hba->iop->inbound_queue); +- } else +- writel(_req->req_shifted_phy | IOPMU_QUEUE_ADDR_HOST_BIT, +- &hba->iop->inbound_queue); +- ++ hba->ops->post_req(hba, _req); + return 0; + + cmd_done: +@@ -563,9 +813,7 @@ static int hptiop_reset_hba(struct hptiop_hba *hba) + { + if (atomic_xchg(&hba->resetting, 1) == 0) { + atomic_inc(&hba->reset_count); +- writel(IOPMU_INBOUND_MSG0_RESET, +- &hba->iop->inbound_msgaddr0); +- hptiop_pci_posting_flush(hba->iop); ++ hba->ops->post_msg(hba, IOPMU_INBOUND_MSG0_RESET); + } + + wait_event_timeout(hba->reset_wq, +@@ -601,8 +849,10 @@ static int hptiop_reset(struct scsi_cmnd *scp) + static int hptiop_adjust_disk_queue_depth(struct scsi_device *sdev, + int queue_depth) + { +- if(queue_depth > 256) +- queue_depth = 256; ++ struct hptiop_hba *hba = (struct hptiop_hba *)sdev->host->hostdata; ++ ++ if (queue_depth > hba->max_requests) ++ queue_depth = hba->max_requests; + scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth); + return queue_depth; + } +@@ -663,6 +913,26 @@ static struct scsi_host_template driver_template = { + .change_queue_depth = hptiop_adjust_disk_queue_depth, + }; + ++static int hptiop_internal_memalloc_mv(struct hptiop_hba *hba) ++{ ++ hba->u.mv.internal_req = dma_alloc_coherent(&hba->pcidev->dev, ++ 0x800, &hba->u.mv.internal_req_phy, GFP_KERNEL); ++ if (hba->u.mv.internal_req) ++ return 0; ++ else ++ return -1; ++} ++ ++static int hptiop_internal_memfree_mv(struct hptiop_hba *hba) ++{ ++ if (hba->u.mv.internal_req) { ++ dma_free_coherent(&hba->pcidev->dev, 0x800, ++ hba->u.mv.internal_req, hba->u.mv.internal_req_phy); ++ return 0; ++ } else ++ return -1; ++} ++ + static int __devinit hptiop_probe(struct pci_dev *pcidev, + const struct pci_device_id *id) + { +@@ -708,6 +978,7 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, + + hba = (struct hptiop_hba *)host->hostdata; + ++ hba->ops = (struct hptiop_adapter_ops *)id->driver_data; + hba->pcidev = pcidev; + hba->host = host; + hba->initialized = 0; +@@ -725,16 +996,24 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, + host->n_io_port = 0; + host->irq = pcidev->irq; + +- if (hptiop_map_pci_bar(hba)) ++ if (hba->ops->map_pci_bar(hba)) + goto free_scsi_host; + +- if (iop_wait_ready(hba->iop, 20000)) { ++ if (hba->ops->iop_wait_ready(hba, 20000)) { + printk(KERN_ERR "scsi%d: firmware not ready\n", + hba->host->host_no); + goto unmap_pci_bar; + } + +- if (iop_get_config(hba, &iop_config)) { ++ if (hba->ops->internal_memalloc) { ++ if (hba->ops->internal_memalloc(hba)) { ++ printk(KERN_ERR "scsi%d: internal_memalloc failed\n", ++ hba->host->host_no); ++ goto unmap_pci_bar; ++ } ++ } ++ ++ if (hba->ops->get_config(hba, &iop_config)) { + printk(KERN_ERR "scsi%d: get config failed\n", + hba->host->host_no); + goto unmap_pci_bar; +@@ -770,7 +1049,7 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, + set_config.vbus_id = cpu_to_le16(host->host_no); + set_config.max_host_request_size = cpu_to_le16(req_size); + +- if (iop_set_config(hba, &set_config)) { ++ if (hba->ops->set_config(hba, &set_config)) { + printk(KERN_ERR "scsi%d: set config failed\n", + hba->host->host_no); + goto unmap_pci_bar; +@@ -839,21 +1118,24 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, + + free_request_mem: + dma_free_coherent(&hba->pcidev->dev, +- hba->req_size*hba->max_requests + 0x20, ++ hba->req_size * hba->max_requests + 0x20, + hba->dma_coherent, hba->dma_coherent_handle); + + free_request_irq: + free_irq(hba->pcidev->irq, hba); + + unmap_pci_bar: +- iounmap(hba->iop); ++ if (hba->ops->internal_memfree) ++ hba->ops->internal_memfree(hba); + +-free_pci_regions: +- pci_release_regions(pcidev) ; ++ hba->ops->unmap_pci_bar(hba); + + free_scsi_host: + scsi_host_put(host); + ++free_pci_regions: ++ pci_release_regions(pcidev); ++ + disable_pci_device: + pci_disable_device(pcidev); + +@@ -865,8 +1147,6 @@ static void hptiop_shutdown(struct pci_dev *pcidev) + { + struct Scsi_Host *host = pci_get_drvdata(pcidev); + struct hptiop_hba *hba = (struct hptiop_hba *)host->hostdata; +- struct hpt_iopmu __iomem *iop = hba->iop; +- u32 int_mask; + + dprintk("hptiop_shutdown(%p)\n", hba); + +@@ -876,11 +1156,24 @@ static void hptiop_shutdown(struct pci_dev *pcidev) + hba->host->host_no); + + /* disable all outbound interrupts */ +- int_mask = readl(&iop->outbound_intmask); ++ hba->ops->disable_intr(hba); ++} ++ ++static void hptiop_disable_intr_itl(struct hptiop_hba *hba) ++{ ++ u32 int_mask; ++ ++ int_mask = readl(&hba->u.itl.iop->outbound_intmask); + writel(int_mask | + IOPMU_OUTBOUND_INT_MSG0 | IOPMU_OUTBOUND_INT_POSTQUEUE, +- &iop->outbound_intmask); +- hptiop_pci_posting_flush(iop); ++ &hba->u.itl.iop->outbound_intmask); ++ readl(&hba->u.itl.iop->outbound_intmask); ++} ++ ++static void hptiop_disable_intr_mv(struct hptiop_hba *hba) ++{ ++ writel(0, &hba->u.mv.regs->outbound_intmask); ++ readl(&hba->u.mv.regs->outbound_intmask); + } + + static void hptiop_remove(struct pci_dev *pcidev) +@@ -901,7 +1194,10 @@ static void hptiop_remove(struct pci_dev *pcidev) + hba->dma_coherent, + hba->dma_coherent_handle); + +- iounmap(hba->iop); ++ if (hba->ops->internal_memfree) ++ hba->ops->internal_memfree(hba); ++ ++ hba->ops->unmap_pci_bar(hba); + + pci_release_regions(hba->pcidev); + pci_set_drvdata(hba->pcidev, NULL); +@@ -910,11 +1206,50 @@ static void hptiop_remove(struct pci_dev *pcidev) + scsi_host_put(host); + } + ++static struct hptiop_adapter_ops hptiop_itl_ops = { ++ .iop_wait_ready = iop_wait_ready_itl, ++ .internal_memalloc = 0, ++ .internal_memfree = 0, ++ .map_pci_bar = hptiop_map_pci_bar_itl, ++ .unmap_pci_bar = hptiop_unmap_pci_bar_itl, ++ .enable_intr = hptiop_enable_intr_itl, ++ .disable_intr = hptiop_disable_intr_itl, ++ .get_config = iop_get_config_itl, ++ .set_config = iop_set_config_itl, ++ .iop_intr = iop_intr_itl, ++ .post_msg = hptiop_post_msg_itl, ++ .post_req = hptiop_post_req_itl, ++}; ++ ++static struct hptiop_adapter_ops hptiop_mv_ops = { ++ .iop_wait_ready = iop_wait_ready_mv, ++ .internal_memalloc = hptiop_internal_memalloc_mv, ++ .internal_memfree = hptiop_internal_memfree_mv, ++ .map_pci_bar = hptiop_map_pci_bar_mv, ++ .unmap_pci_bar = hptiop_unmap_pci_bar_mv, ++ .enable_intr = hptiop_enable_intr_mv, ++ .disable_intr = hptiop_disable_intr_mv, ++ .get_config = iop_get_config_mv, ++ .set_config = iop_set_config_mv, ++ .iop_intr = iop_intr_mv, ++ .post_msg = hptiop_post_msg_mv, ++ .post_req = hptiop_post_req_mv, ++}; ++ + static struct pci_device_id hptiop_id_table[] = { +- { PCI_VDEVICE(TTI, 0x3220) }, +- { PCI_VDEVICE(TTI, 0x3320) }, +- { PCI_VDEVICE(TTI, 0x3520) }, +- { PCI_VDEVICE(TTI, 0x4320) }, ++ { PCI_VDEVICE(TTI, 0x3220), (kernel_ulong_t)&hptiop_itl_ops }, ++ { PCI_VDEVICE(TTI, 0x3320), (kernel_ulong_t)&hptiop_itl_ops }, ++ { PCI_VDEVICE(TTI, 0x3520), (kernel_ulong_t)&hptiop_itl_ops }, ++ { PCI_VDEVICE(TTI, 0x4320), (kernel_ulong_t)&hptiop_itl_ops }, ++ { PCI_VDEVICE(TTI, 0x3510), (kernel_ulong_t)&hptiop_itl_ops }, ++ { PCI_VDEVICE(TTI, 0x3511), (kernel_ulong_t)&hptiop_itl_ops }, ++ { PCI_VDEVICE(TTI, 0x3521), (kernel_ulong_t)&hptiop_itl_ops }, ++ { PCI_VDEVICE(TTI, 0x3522), (kernel_ulong_t)&hptiop_itl_ops }, ++ { PCI_VDEVICE(TTI, 0x3410), (kernel_ulong_t)&hptiop_itl_ops }, ++ { PCI_VDEVICE(TTI, 0x3540), (kernel_ulong_t)&hptiop_itl_ops }, ++ { PCI_VDEVICE(TTI, 0x3120), (kernel_ulong_t)&hptiop_mv_ops }, ++ { PCI_VDEVICE(TTI, 0x3122), (kernel_ulong_t)&hptiop_mv_ops }, ++ { PCI_VDEVICE(TTI, 0x3020), (kernel_ulong_t)&hptiop_mv_ops }, + {}, + }; + +diff --git a/drivers/scsi/hptiop.h b/drivers/scsi/hptiop.h +index 2a5e46e..a0289f2 100644 +--- a/drivers/scsi/hptiop.h ++++ b/drivers/scsi/hptiop.h +@@ -1,5 +1,5 @@ + /* +- * HighPoint RR3xxx controller driver for Linux ++ * HighPoint RR3xxx/4xxx controller driver for Linux + * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify +@@ -18,8 +18,7 @@ + #ifndef _HPTIOP_H_ + #define _HPTIOP_H_ + +-struct hpt_iopmu +-{ ++struct hpt_iopmu_itl { + __le32 resrved0[4]; + __le32 inbound_msgaddr0; + __le32 inbound_msgaddr1; +@@ -54,6 +53,40 @@ struct hpt_iopmu + #define IOPMU_INBOUND_INT_ERROR 8 + #define IOPMU_INBOUND_INT_POSTQUEUE 0x10 + ++#define MVIOP_QUEUE_LEN 512 ++ ++struct hpt_iopmu_mv { ++ __le32 inbound_head; ++ __le32 inbound_tail; ++ __le32 outbound_head; ++ __le32 outbound_tail; ++ __le32 inbound_msg; ++ __le32 outbound_msg; ++ __le32 reserve[10]; ++ __le64 inbound_q[MVIOP_QUEUE_LEN]; ++ __le64 outbound_q[MVIOP_QUEUE_LEN]; ++}; ++ ++struct hpt_iopmv_regs { ++ __le32 reserved[0x20400 / 4]; ++ __le32 inbound_doorbell; ++ __le32 inbound_intmask; ++ __le32 outbound_doorbell; ++ __le32 outbound_intmask; ++}; ++ ++#define MVIOP_MU_QUEUE_ADDR_HOST_MASK (~(0x1full)) ++#define MVIOP_MU_QUEUE_ADDR_HOST_BIT 4 ++ ++#define MVIOP_MU_QUEUE_ADDR_IOP_HIGH32 0xffffffff ++#define MVIOP_MU_QUEUE_REQUEST_RESULT_BIT 1 ++#define MVIOP_MU_QUEUE_REQUEST_RETURN_CONTEXT 2 ++ ++#define MVIOP_MU_INBOUND_INT_MSG 1 ++#define MVIOP_MU_INBOUND_INT_POSTQUEUE 2 ++#define MVIOP_MU_OUTBOUND_INT_MSG 1 ++#define MVIOP_MU_OUTBOUND_INT_POSTQUEUE 2 ++ + enum hpt_iopmu_message { + /* host-to-iop messages */ + IOPMU_INBOUND_MSG0_NOP = 0, +@@ -72,8 +105,7 @@ enum hpt_iopmu_message { + IOPMU_OUTBOUND_MSG0_REVALIDATE_DEVICE_MAX = 0x3ff, + }; + +-struct hpt_iop_request_header +-{ ++struct hpt_iop_request_header { + __le32 size; + __le32 type; + __le32 flags; +@@ -104,11 +136,10 @@ enum hpt_iop_result_type { + IOP_RESULT_RESET, + IOP_RESULT_INVALID_REQUEST, + IOP_RESULT_BAD_TARGET, +- IOP_RESULT_MODE_SENSE_CHECK_CONDITION, ++ IOP_RESULT_CHECK_CONDITION, + }; + +-struct hpt_iop_request_get_config +-{ ++struct hpt_iop_request_get_config { + struct hpt_iop_request_header header; + __le32 interface_version; + __le32 firmware_version; +@@ -121,8 +152,7 @@ struct hpt_iop_request_get_config + __le32 sdram_size; + }; + +-struct hpt_iop_request_set_config +-{ ++struct hpt_iop_request_set_config { + struct hpt_iop_request_header header; + __le32 iop_id; + __le16 vbus_id; +@@ -130,15 +160,13 @@ struct hpt_iop_request_set_config + __le32 reserve[6]; + }; + +-struct hpt_iopsg +-{ ++struct hpt_iopsg { + __le32 size; + __le32 eot; /* non-zero: end of table */ + __le64 pci_address; + }; + +-struct hpt_iop_request_block_command +-{ ++struct hpt_iop_request_block_command { + struct hpt_iop_request_header header; + u8 channel; + u8 target; +@@ -156,8 +184,7 @@ struct hpt_iop_request_block_command + #define IOP_BLOCK_COMMAND_FLUSH 4 + #define IOP_BLOCK_COMMAND_SHUTDOWN 5 + +-struct hpt_iop_request_scsi_command +-{ ++struct hpt_iop_request_scsi_command { + struct hpt_iop_request_header header; + u8 channel; + u8 target; +@@ -168,8 +195,7 @@ struct hpt_iop_request_scsi_command + struct hpt_iopsg sg_list[1]; + }; + +-struct hpt_iop_request_ioctl_command +-{ ++struct hpt_iop_request_ioctl_command { + struct hpt_iop_request_header header; + __le32 ioctl_code; + __le32 inbuf_size; +@@ -182,11 +208,11 @@ struct hpt_iop_request_ioctl_command + #define HPTIOP_MAX_REQUESTS 256u + + struct hptiop_request { +- struct hptiop_request * next; +- void * req_virt; +- u32 req_shifted_phy; +- struct scsi_cmnd * scp; +- int index; ++ struct hptiop_request *next; ++ void *req_virt; ++ u32 req_shifted_phy; ++ struct scsi_cmnd *scp; ++ int index; + }; + + struct hpt_scsi_pointer { +@@ -198,9 +224,21 @@ struct hpt_scsi_pointer { + #define HPT_SCP(scp) ((struct hpt_scsi_pointer *)&(scp)->SCp) + + struct hptiop_hba { +- struct hpt_iopmu __iomem * iop; +- struct Scsi_Host * host; +- struct pci_dev * pcidev; ++ struct hptiop_adapter_ops *ops; ++ union { ++ struct { ++ struct hpt_iopmu_itl __iomem *iop; ++ } itl; ++ struct { ++ struct hpt_iopmv_regs *regs; ++ struct hpt_iopmu_mv __iomem *mu; ++ void *internal_req; ++ dma_addr_t internal_req_phy; ++ } mv; ++ } u; ++ ++ struct Scsi_Host *host; ++ struct pci_dev *pcidev; + + /* IOP config info */ + u32 interface_version; +@@ -213,15 +251,15 @@ struct hptiop_hba { + + u32 req_size; /* host-allocated request buffer size */ + +- int iopintf_v2: 1; +- int initialized: 1; +- int msg_done: 1; ++ u32 iopintf_v2: 1; ++ u32 initialized: 1; ++ u32 msg_done: 1; + + struct hptiop_request * req_list; + struct hptiop_request reqs[HPTIOP_MAX_REQUESTS]; + + /* used to free allocated dma area */ +- void * dma_coherent; ++ void *dma_coherent; + dma_addr_t dma_coherent_handle; + + atomic_t reset_count; +@@ -231,19 +269,35 @@ struct hptiop_hba { + wait_queue_head_t ioctl_wq; + }; + +-struct hpt_ioctl_k +-{ ++struct hpt_ioctl_k { + struct hptiop_hba * hba; + u32 ioctl_code; + u32 inbuf_size; + u32 outbuf_size; +- void * inbuf; +- void * outbuf; +- u32 * bytes_returned; ++ void *inbuf; ++ void *outbuf; ++ u32 *bytes_returned; + void (*done)(struct hpt_ioctl_k *); + int result; /* HPT_IOCTL_RESULT_ */ + }; + ++struct hptiop_adapter_ops { ++ int (*iop_wait_ready)(struct hptiop_hba *hba, u32 millisec); ++ int (*internal_memalloc)(struct hptiop_hba *hba); ++ int (*internal_memfree)(struct hptiop_hba *hba); ++ int (*map_pci_bar)(struct hptiop_hba *hba); ++ void (*unmap_pci_bar)(struct hptiop_hba *hba); ++ void (*enable_intr)(struct hptiop_hba *hba); ++ void (*disable_intr)(struct hptiop_hba *hba); ++ int (*get_config)(struct hptiop_hba *hba, ++ struct hpt_iop_request_get_config *config); ++ int (*set_config)(struct hptiop_hba *hba, ++ struct hpt_iop_request_set_config *config); ++ int (*iop_intr)(struct hptiop_hba *hba); ++ void (*post_msg)(struct hptiop_hba *hba, u32 msg); ++ void (*post_req)(struct hptiop_hba *hba, struct hptiop_request *_req); ++}; ++ + #define HPT_IOCTL_RESULT_OK 0 + #define HPT_IOCTL_RESULT_FAILED (-1) + Added: dists/sid/linux-2.6/debian/patches/series/3 ============================================================================== --- (empty file) +++ dists/sid/linux-2.6/debian/patches/series/3 Fri Feb 1 14:58:28 2008 @@ -0,0 +1 @@ ++ features/all/hptiop-update.patch _______________________________________________ Kernel-svn-changes mailing list [email protected] http://lists.alioth.debian.org/mailman/listinfo/kernel-svn-changes

