xref: /linux/drivers/scsi/myrs.c (revision 4bdc0d676a643140bdf17dbf7eafedee3d496a3c)
177266186SHannes Reinecke // SPDX-License-Identifier: GPL-2.0
277266186SHannes Reinecke /*
377266186SHannes Reinecke  * Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers
477266186SHannes Reinecke  *
577266186SHannes Reinecke  * This driver supports the newer, SCSI-based firmware interface only.
677266186SHannes Reinecke  *
777266186SHannes Reinecke  * Copyright 2017 Hannes Reinecke, SUSE Linux GmbH <hare@suse.com>
877266186SHannes Reinecke  *
977266186SHannes Reinecke  * Based on the original DAC960 driver, which has
1077266186SHannes Reinecke  * Copyright 1998-2001 by Leonard N. Zubkoff <lnz@dandelion.com>
1177266186SHannes Reinecke  * Portions Copyright 2002 by Mylex (An IBM Business Unit)
1277266186SHannes Reinecke  */
1377266186SHannes Reinecke 
1477266186SHannes Reinecke #include <linux/module.h>
1577266186SHannes Reinecke #include <linux/types.h>
1677266186SHannes Reinecke #include <linux/delay.h>
1777266186SHannes Reinecke #include <linux/interrupt.h>
1877266186SHannes Reinecke #include <linux/pci.h>
1977266186SHannes Reinecke #include <linux/raid_class.h>
2077266186SHannes Reinecke #include <asm/unaligned.h>
2177266186SHannes Reinecke #include <scsi/scsi.h>
2277266186SHannes Reinecke #include <scsi/scsi_host.h>
2377266186SHannes Reinecke #include <scsi/scsi_device.h>
2477266186SHannes Reinecke #include <scsi/scsi_cmnd.h>
2577266186SHannes Reinecke #include <scsi/scsi_tcq.h>
2677266186SHannes Reinecke #include "myrs.h"
2777266186SHannes Reinecke 
2877266186SHannes Reinecke static struct raid_template *myrs_raid_template;
2977266186SHannes Reinecke 
3077266186SHannes Reinecke static struct myrs_devstate_name_entry {
3177266186SHannes Reinecke 	enum myrs_devstate state;
3277266186SHannes Reinecke 	char *name;
3377266186SHannes Reinecke } myrs_devstate_name_list[] = {
3477266186SHannes Reinecke 	{ MYRS_DEVICE_UNCONFIGURED, "Unconfigured" },
3577266186SHannes Reinecke 	{ MYRS_DEVICE_ONLINE, "Online" },
3677266186SHannes Reinecke 	{ MYRS_DEVICE_REBUILD, "Rebuild" },
3777266186SHannes Reinecke 	{ MYRS_DEVICE_MISSING, "Missing" },
3877266186SHannes Reinecke 	{ MYRS_DEVICE_SUSPECTED_CRITICAL, "SuspectedCritical" },
3977266186SHannes Reinecke 	{ MYRS_DEVICE_OFFLINE, "Offline" },
4077266186SHannes Reinecke 	{ MYRS_DEVICE_CRITICAL, "Critical" },
4177266186SHannes Reinecke 	{ MYRS_DEVICE_SUSPECTED_DEAD, "SuspectedDead" },
4277266186SHannes Reinecke 	{ MYRS_DEVICE_COMMANDED_OFFLINE, "CommandedOffline" },
4377266186SHannes Reinecke 	{ MYRS_DEVICE_STANDBY, "Standby" },
4477266186SHannes Reinecke 	{ MYRS_DEVICE_INVALID_STATE, "Invalid" },
4577266186SHannes Reinecke };
4677266186SHannes Reinecke 
4777266186SHannes Reinecke static char *myrs_devstate_name(enum myrs_devstate state)
4877266186SHannes Reinecke {
4977266186SHannes Reinecke 	struct myrs_devstate_name_entry *entry = myrs_devstate_name_list;
5077266186SHannes Reinecke 	int i;
5177266186SHannes Reinecke 
5277266186SHannes Reinecke 	for (i = 0; i < ARRAY_SIZE(myrs_devstate_name_list); i++) {
5377266186SHannes Reinecke 		if (entry[i].state == state)
5477266186SHannes Reinecke 			return entry[i].name;
5577266186SHannes Reinecke 	}
5677266186SHannes Reinecke 	return NULL;
5777266186SHannes Reinecke }
5877266186SHannes Reinecke 
5977266186SHannes Reinecke static struct myrs_raid_level_name_entry {
6077266186SHannes Reinecke 	enum myrs_raid_level level;
6177266186SHannes Reinecke 	char *name;
6277266186SHannes Reinecke } myrs_raid_level_name_list[] = {
6377266186SHannes Reinecke 	{ MYRS_RAID_LEVEL0, "RAID0" },
6477266186SHannes Reinecke 	{ MYRS_RAID_LEVEL1, "RAID1" },
6577266186SHannes Reinecke 	{ MYRS_RAID_LEVEL3, "RAID3 right asymmetric parity" },
6677266186SHannes Reinecke 	{ MYRS_RAID_LEVEL5, "RAID5 right asymmetric parity" },
6777266186SHannes Reinecke 	{ MYRS_RAID_LEVEL6, "RAID6" },
6877266186SHannes Reinecke 	{ MYRS_RAID_JBOD, "JBOD" },
6977266186SHannes Reinecke 	{ MYRS_RAID_NEWSPAN, "New Mylex SPAN" },
7077266186SHannes Reinecke 	{ MYRS_RAID_LEVEL3F, "RAID3 fixed parity" },
7177266186SHannes Reinecke 	{ MYRS_RAID_LEVEL3L, "RAID3 left symmetric parity" },
7277266186SHannes Reinecke 	{ MYRS_RAID_SPAN, "Mylex SPAN" },
7377266186SHannes Reinecke 	{ MYRS_RAID_LEVEL5L, "RAID5 left symmetric parity" },
7477266186SHannes Reinecke 	{ MYRS_RAID_LEVELE, "RAIDE (concatenation)" },
7577266186SHannes Reinecke 	{ MYRS_RAID_PHYSICAL, "Physical device" },
7677266186SHannes Reinecke };
7777266186SHannes Reinecke 
7877266186SHannes Reinecke static char *myrs_raid_level_name(enum myrs_raid_level level)
7977266186SHannes Reinecke {
8077266186SHannes Reinecke 	struct myrs_raid_level_name_entry *entry = myrs_raid_level_name_list;
8177266186SHannes Reinecke 	int i;
8277266186SHannes Reinecke 
8377266186SHannes Reinecke 	for (i = 0; i < ARRAY_SIZE(myrs_raid_level_name_list); i++) {
8477266186SHannes Reinecke 		if (entry[i].level == level)
8577266186SHannes Reinecke 			return entry[i].name;
8677266186SHannes Reinecke 	}
8777266186SHannes Reinecke 	return NULL;
8877266186SHannes Reinecke }
8977266186SHannes Reinecke 
9077266186SHannes Reinecke /**
9177266186SHannes Reinecke  * myrs_reset_cmd - clears critical fields in struct myrs_cmdblk
9277266186SHannes Reinecke  */
9377266186SHannes Reinecke static inline void myrs_reset_cmd(struct myrs_cmdblk *cmd_blk)
9477266186SHannes Reinecke {
9577266186SHannes Reinecke 	union myrs_cmd_mbox *mbox = &cmd_blk->mbox;
9677266186SHannes Reinecke 
9777266186SHannes Reinecke 	memset(mbox, 0, sizeof(union myrs_cmd_mbox));
9877266186SHannes Reinecke 	cmd_blk->status = 0;
9977266186SHannes Reinecke }
10077266186SHannes Reinecke 
10177266186SHannes Reinecke /**
10277266186SHannes Reinecke  * myrs_qcmd - queues Command for DAC960 V2 Series Controllers.
10377266186SHannes Reinecke  */
10477266186SHannes Reinecke static void myrs_qcmd(struct myrs_hba *cs, struct myrs_cmdblk *cmd_blk)
10577266186SHannes Reinecke {
10677266186SHannes Reinecke 	void __iomem *base = cs->io_base;
10777266186SHannes Reinecke 	union myrs_cmd_mbox *mbox = &cmd_blk->mbox;
10877266186SHannes Reinecke 	union myrs_cmd_mbox *next_mbox = cs->next_cmd_mbox;
10977266186SHannes Reinecke 
11077266186SHannes Reinecke 	cs->write_cmd_mbox(next_mbox, mbox);
11177266186SHannes Reinecke 
11277266186SHannes Reinecke 	if (cs->prev_cmd_mbox1->words[0] == 0 ||
11377266186SHannes Reinecke 	    cs->prev_cmd_mbox2->words[0] == 0)
11477266186SHannes Reinecke 		cs->get_cmd_mbox(base);
11577266186SHannes Reinecke 
11677266186SHannes Reinecke 	cs->prev_cmd_mbox2 = cs->prev_cmd_mbox1;
11777266186SHannes Reinecke 	cs->prev_cmd_mbox1 = next_mbox;
11877266186SHannes Reinecke 
11977266186SHannes Reinecke 	if (++next_mbox > cs->last_cmd_mbox)
12077266186SHannes Reinecke 		next_mbox = cs->first_cmd_mbox;
12177266186SHannes Reinecke 
12277266186SHannes Reinecke 	cs->next_cmd_mbox = next_mbox;
12377266186SHannes Reinecke }
12477266186SHannes Reinecke 
12577266186SHannes Reinecke /**
12677266186SHannes Reinecke  * myrs_exec_cmd - executes V2 Command and waits for completion.
12777266186SHannes Reinecke  */
12877266186SHannes Reinecke static void myrs_exec_cmd(struct myrs_hba *cs,
12977266186SHannes Reinecke 		struct myrs_cmdblk *cmd_blk)
13077266186SHannes Reinecke {
13177266186SHannes Reinecke 	DECLARE_COMPLETION_ONSTACK(complete);
13277266186SHannes Reinecke 	unsigned long flags;
13377266186SHannes Reinecke 
13477266186SHannes Reinecke 	cmd_blk->complete = &complete;
13577266186SHannes Reinecke 	spin_lock_irqsave(&cs->queue_lock, flags);
13677266186SHannes Reinecke 	myrs_qcmd(cs, cmd_blk);
13777266186SHannes Reinecke 	spin_unlock_irqrestore(&cs->queue_lock, flags);
13877266186SHannes Reinecke 
13977266186SHannes Reinecke 	WARN_ON(in_interrupt());
14077266186SHannes Reinecke 	wait_for_completion(&complete);
14177266186SHannes Reinecke }
14277266186SHannes Reinecke 
14377266186SHannes Reinecke /**
14477266186SHannes Reinecke  * myrs_report_progress - prints progress message
14577266186SHannes Reinecke  */
14677266186SHannes Reinecke static void myrs_report_progress(struct myrs_hba *cs, unsigned short ldev_num,
14777266186SHannes Reinecke 		unsigned char *msg, unsigned long blocks,
14877266186SHannes Reinecke 		unsigned long size)
14977266186SHannes Reinecke {
15077266186SHannes Reinecke 	shost_printk(KERN_INFO, cs->host,
15177266186SHannes Reinecke 		     "Logical Drive %d: %s in Progress: %d%% completed\n",
15277266186SHannes Reinecke 		     ldev_num, msg,
15377266186SHannes Reinecke 		     (100 * (int)(blocks >> 7)) / (int)(size >> 7));
15477266186SHannes Reinecke }
15577266186SHannes Reinecke 
15677266186SHannes Reinecke /**
15777266186SHannes Reinecke  * myrs_get_ctlr_info - executes a Controller Information IOCTL Command
15877266186SHannes Reinecke  */
15977266186SHannes Reinecke static unsigned char myrs_get_ctlr_info(struct myrs_hba *cs)
16077266186SHannes Reinecke {
16177266186SHannes Reinecke 	struct myrs_cmdblk *cmd_blk = &cs->dcmd_blk;
16277266186SHannes Reinecke 	union myrs_cmd_mbox *mbox = &cmd_blk->mbox;
16377266186SHannes Reinecke 	dma_addr_t ctlr_info_addr;
16477266186SHannes Reinecke 	union myrs_sgl *sgl;
16577266186SHannes Reinecke 	unsigned char status;
16677409c4cSArnd Bergmann 	unsigned short ldev_present, ldev_critical, ldev_offline;
16777266186SHannes Reinecke 
16877409c4cSArnd Bergmann 	ldev_present = cs->ctlr_info->ldev_present;
16977409c4cSArnd Bergmann 	ldev_critical = cs->ctlr_info->ldev_critical;
17077409c4cSArnd Bergmann 	ldev_offline = cs->ctlr_info->ldev_offline;
17177409c4cSArnd Bergmann 
17277266186SHannes Reinecke 	ctlr_info_addr = dma_map_single(&cs->pdev->dev, cs->ctlr_info,
17377266186SHannes Reinecke 					sizeof(struct myrs_ctlr_info),
17477266186SHannes Reinecke 					DMA_FROM_DEVICE);
17577266186SHannes Reinecke 	if (dma_mapping_error(&cs->pdev->dev, ctlr_info_addr))
17677266186SHannes Reinecke 		return MYRS_STATUS_FAILED;
17777266186SHannes Reinecke 
17877266186SHannes Reinecke 	mutex_lock(&cs->dcmd_mutex);
17977266186SHannes Reinecke 	myrs_reset_cmd(cmd_blk);
18077266186SHannes Reinecke 	mbox->ctlr_info.id = MYRS_DCMD_TAG;
18177266186SHannes Reinecke 	mbox->ctlr_info.opcode = MYRS_CMD_OP_IOCTL;
18277266186SHannes Reinecke 	mbox->ctlr_info.control.dma_ctrl_to_host = true;
18377266186SHannes Reinecke 	mbox->ctlr_info.control.no_autosense = true;
18477266186SHannes Reinecke 	mbox->ctlr_info.dma_size = sizeof(struct myrs_ctlr_info);
18577266186SHannes Reinecke 	mbox->ctlr_info.ctlr_num = 0;
18677266186SHannes Reinecke 	mbox->ctlr_info.ioctl_opcode = MYRS_IOCTL_GET_CTLR_INFO;
18777266186SHannes Reinecke 	sgl = &mbox->ctlr_info.dma_addr;
18877266186SHannes Reinecke 	sgl->sge[0].sge_addr = ctlr_info_addr;
18977266186SHannes Reinecke 	sgl->sge[0].sge_count = mbox->ctlr_info.dma_size;
19077266186SHannes Reinecke 	dev_dbg(&cs->host->shost_gendev, "Sending GetControllerInfo\n");
19177266186SHannes Reinecke 	myrs_exec_cmd(cs, cmd_blk);
19277266186SHannes Reinecke 	status = cmd_blk->status;
19377266186SHannes Reinecke 	mutex_unlock(&cs->dcmd_mutex);
19477266186SHannes Reinecke 	dma_unmap_single(&cs->pdev->dev, ctlr_info_addr,
19577266186SHannes Reinecke 			 sizeof(struct myrs_ctlr_info), DMA_FROM_DEVICE);
19677266186SHannes Reinecke 	if (status == MYRS_STATUS_SUCCESS) {
19777266186SHannes Reinecke 		if (cs->ctlr_info->bg_init_active +
19877266186SHannes Reinecke 		    cs->ctlr_info->ldev_init_active +
19977266186SHannes Reinecke 		    cs->ctlr_info->pdev_init_active +
20077266186SHannes Reinecke 		    cs->ctlr_info->cc_active +
20177266186SHannes Reinecke 		    cs->ctlr_info->rbld_active +
20277266186SHannes Reinecke 		    cs->ctlr_info->exp_active != 0)
20377266186SHannes Reinecke 			cs->needs_update = true;
20477409c4cSArnd Bergmann 		if (cs->ctlr_info->ldev_present != ldev_present ||
20577409c4cSArnd Bergmann 		    cs->ctlr_info->ldev_critical != ldev_critical ||
20677409c4cSArnd Bergmann 		    cs->ctlr_info->ldev_offline != ldev_offline)
20777266186SHannes Reinecke 			shost_printk(KERN_INFO, cs->host,
20877266186SHannes Reinecke 				     "Logical drive count changes (%d/%d/%d)\n",
20977266186SHannes Reinecke 				     cs->ctlr_info->ldev_critical,
21077266186SHannes Reinecke 				     cs->ctlr_info->ldev_offline,
21177266186SHannes Reinecke 				     cs->ctlr_info->ldev_present);
21277266186SHannes Reinecke 	}
21377266186SHannes Reinecke 
21477266186SHannes Reinecke 	return status;
21577266186SHannes Reinecke }
21677266186SHannes Reinecke 
21777266186SHannes Reinecke /**
21877266186SHannes Reinecke  * myrs_get_ldev_info - executes a Logical Device Information IOCTL Command
21977266186SHannes Reinecke  */
22077266186SHannes Reinecke static unsigned char myrs_get_ldev_info(struct myrs_hba *cs,
22177266186SHannes Reinecke 		unsigned short ldev_num, struct myrs_ldev_info *ldev_info)
22277266186SHannes Reinecke {
22377266186SHannes Reinecke 	struct myrs_cmdblk *cmd_blk = &cs->dcmd_blk;
22477266186SHannes Reinecke 	union myrs_cmd_mbox *mbox = &cmd_blk->mbox;
22577266186SHannes Reinecke 	dma_addr_t ldev_info_addr;
22677266186SHannes Reinecke 	struct myrs_ldev_info ldev_info_orig;
22777266186SHannes Reinecke 	union myrs_sgl *sgl;
22877266186SHannes Reinecke 	unsigned char status;
22977266186SHannes Reinecke 
23077266186SHannes Reinecke 	memcpy(&ldev_info_orig, ldev_info, sizeof(struct myrs_ldev_info));
23177266186SHannes Reinecke 	ldev_info_addr = dma_map_single(&cs->pdev->dev, ldev_info,
23277266186SHannes Reinecke 					sizeof(struct myrs_ldev_info),
23377266186SHannes Reinecke 					DMA_FROM_DEVICE);
23477266186SHannes Reinecke 	if (dma_mapping_error(&cs->pdev->dev, ldev_info_addr))
23577266186SHannes Reinecke 		return MYRS_STATUS_FAILED;
23677266186SHannes Reinecke 
23777266186SHannes Reinecke 	mutex_lock(&cs->dcmd_mutex);
23877266186SHannes Reinecke 	myrs_reset_cmd(cmd_blk);
23977266186SHannes Reinecke 	mbox->ldev_info.id = MYRS_DCMD_TAG;
24077266186SHannes Reinecke 	mbox->ldev_info.opcode = MYRS_CMD_OP_IOCTL;
24177266186SHannes Reinecke 	mbox->ldev_info.control.dma_ctrl_to_host = true;
24277266186SHannes Reinecke 	mbox->ldev_info.control.no_autosense = true;
24377266186SHannes Reinecke 	mbox->ldev_info.dma_size = sizeof(struct myrs_ldev_info);
24477266186SHannes Reinecke 	mbox->ldev_info.ldev.ldev_num = ldev_num;
24577266186SHannes Reinecke 	mbox->ldev_info.ioctl_opcode = MYRS_IOCTL_GET_LDEV_INFO_VALID;
24677266186SHannes Reinecke 	sgl = &mbox->ldev_info.dma_addr;
24777266186SHannes Reinecke 	sgl->sge[0].sge_addr = ldev_info_addr;
24877266186SHannes Reinecke 	sgl->sge[0].sge_count = mbox->ldev_info.dma_size;
24977266186SHannes Reinecke 	dev_dbg(&cs->host->shost_gendev,
25077266186SHannes Reinecke 		"Sending GetLogicalDeviceInfoValid for ldev %d\n", ldev_num);
25177266186SHannes Reinecke 	myrs_exec_cmd(cs, cmd_blk);
25277266186SHannes Reinecke 	status = cmd_blk->status;
25377266186SHannes Reinecke 	mutex_unlock(&cs->dcmd_mutex);
25477266186SHannes Reinecke 	dma_unmap_single(&cs->pdev->dev, ldev_info_addr,
25577266186SHannes Reinecke 			 sizeof(struct myrs_ldev_info), DMA_FROM_DEVICE);
25677266186SHannes Reinecke 	if (status == MYRS_STATUS_SUCCESS) {
25777266186SHannes Reinecke 		unsigned short ldev_num = ldev_info->ldev_num;
25877266186SHannes Reinecke 		struct myrs_ldev_info *new = ldev_info;
25977266186SHannes Reinecke 		struct myrs_ldev_info *old = &ldev_info_orig;
26077266186SHannes Reinecke 		unsigned long ldev_size = new->cfg_devsize;
26177266186SHannes Reinecke 
26277266186SHannes Reinecke 		if (new->dev_state != old->dev_state) {
26377266186SHannes Reinecke 			const char *name;
26477266186SHannes Reinecke 
26577266186SHannes Reinecke 			name = myrs_devstate_name(new->dev_state);
26677266186SHannes Reinecke 			shost_printk(KERN_INFO, cs->host,
26777266186SHannes Reinecke 				     "Logical Drive %d is now %s\n",
26877266186SHannes Reinecke 				     ldev_num, name ? name : "Invalid");
26977266186SHannes Reinecke 		}
27077266186SHannes Reinecke 		if ((new->soft_errs != old->soft_errs) ||
27177266186SHannes Reinecke 		    (new->cmds_failed != old->cmds_failed) ||
27277266186SHannes Reinecke 		    (new->deferred_write_errs != old->deferred_write_errs))
27377266186SHannes Reinecke 			shost_printk(KERN_INFO, cs->host,
27477266186SHannes Reinecke 				     "Logical Drive %d Errors: Soft = %d, Failed = %d, Deferred Write = %d\n",
27577266186SHannes Reinecke 				     ldev_num, new->soft_errs,
27677266186SHannes Reinecke 				     new->cmds_failed,
27777266186SHannes Reinecke 				     new->deferred_write_errs);
27877266186SHannes Reinecke 		if (new->bg_init_active)
27977266186SHannes Reinecke 			myrs_report_progress(cs, ldev_num,
28077266186SHannes Reinecke 					     "Background Initialization",
28177266186SHannes Reinecke 					     new->bg_init_lba, ldev_size);
28277266186SHannes Reinecke 		else if (new->fg_init_active)
28377266186SHannes Reinecke 			myrs_report_progress(cs, ldev_num,
28477266186SHannes Reinecke 					     "Foreground Initialization",
28577266186SHannes Reinecke 					     new->fg_init_lba, ldev_size);
28677266186SHannes Reinecke 		else if (new->migration_active)
28777266186SHannes Reinecke 			myrs_report_progress(cs, ldev_num,
28877266186SHannes Reinecke 					     "Data Migration",
28977266186SHannes Reinecke 					     new->migration_lba, ldev_size);
29077266186SHannes Reinecke 		else if (new->patrol_active)
29177266186SHannes Reinecke 			myrs_report_progress(cs, ldev_num,
29277266186SHannes Reinecke 					     "Patrol Operation",
29377266186SHannes Reinecke 					     new->patrol_lba, ldev_size);
29477266186SHannes Reinecke 		if (old->bg_init_active && !new->bg_init_active)
29577266186SHannes Reinecke 			shost_printk(KERN_INFO, cs->host,
29677266186SHannes Reinecke 				     "Logical Drive %d: Background Initialization %s\n",
29777266186SHannes Reinecke 				     ldev_num,
29877266186SHannes Reinecke 				     (new->ldev_control.ldev_init_done ?
29977266186SHannes Reinecke 				      "Completed" : "Failed"));
30077266186SHannes Reinecke 	}
30177266186SHannes Reinecke 	return status;
30277266186SHannes Reinecke }
30377266186SHannes Reinecke 
30477266186SHannes Reinecke /**
30577266186SHannes Reinecke  * myrs_get_pdev_info - executes a "Read Physical Device Information" Command
30677266186SHannes Reinecke  */
30777266186SHannes Reinecke static unsigned char myrs_get_pdev_info(struct myrs_hba *cs,
30877266186SHannes Reinecke 		unsigned char channel, unsigned char target, unsigned char lun,
30977266186SHannes Reinecke 		struct myrs_pdev_info *pdev_info)
31077266186SHannes Reinecke {
31177266186SHannes Reinecke 	struct myrs_cmdblk *cmd_blk = &cs->dcmd_blk;
31277266186SHannes Reinecke 	union myrs_cmd_mbox *mbox = &cmd_blk->mbox;
31377266186SHannes Reinecke 	dma_addr_t pdev_info_addr;
31477266186SHannes Reinecke 	union myrs_sgl *sgl;
31577266186SHannes Reinecke 	unsigned char status;
31677266186SHannes Reinecke 
31777266186SHannes Reinecke 	pdev_info_addr = dma_map_single(&cs->pdev->dev, pdev_info,
31877266186SHannes Reinecke 					sizeof(struct myrs_pdev_info),
31977266186SHannes Reinecke 					DMA_FROM_DEVICE);
32077266186SHannes Reinecke 	if (dma_mapping_error(&cs->pdev->dev, pdev_info_addr))
32177266186SHannes Reinecke 		return MYRS_STATUS_FAILED;
32277266186SHannes Reinecke 
32377266186SHannes Reinecke 	mutex_lock(&cs->dcmd_mutex);
32477266186SHannes Reinecke 	myrs_reset_cmd(cmd_blk);
32577266186SHannes Reinecke 	mbox->pdev_info.opcode = MYRS_CMD_OP_IOCTL;
32677266186SHannes Reinecke 	mbox->pdev_info.id = MYRS_DCMD_TAG;
32777266186SHannes Reinecke 	mbox->pdev_info.control.dma_ctrl_to_host = true;
32877266186SHannes Reinecke 	mbox->pdev_info.control.no_autosense = true;
32977266186SHannes Reinecke 	mbox->pdev_info.dma_size = sizeof(struct myrs_pdev_info);
33077266186SHannes Reinecke 	mbox->pdev_info.pdev.lun = lun;
33177266186SHannes Reinecke 	mbox->pdev_info.pdev.target = target;
33277266186SHannes Reinecke 	mbox->pdev_info.pdev.channel = channel;
33377266186SHannes Reinecke 	mbox->pdev_info.ioctl_opcode = MYRS_IOCTL_GET_PDEV_INFO_VALID;
33477266186SHannes Reinecke 	sgl = &mbox->pdev_info.dma_addr;
33577266186SHannes Reinecke 	sgl->sge[0].sge_addr = pdev_info_addr;
33677266186SHannes Reinecke 	sgl->sge[0].sge_count = mbox->pdev_info.dma_size;
33777266186SHannes Reinecke 	dev_dbg(&cs->host->shost_gendev,
33877266186SHannes Reinecke 		"Sending GetPhysicalDeviceInfoValid for pdev %d:%d:%d\n",
33977266186SHannes Reinecke 		channel, target, lun);
34077266186SHannes Reinecke 	myrs_exec_cmd(cs, cmd_blk);
34177266186SHannes Reinecke 	status = cmd_blk->status;
34277266186SHannes Reinecke 	mutex_unlock(&cs->dcmd_mutex);
34377266186SHannes Reinecke 	dma_unmap_single(&cs->pdev->dev, pdev_info_addr,
34477266186SHannes Reinecke 			 sizeof(struct myrs_pdev_info), DMA_FROM_DEVICE);
34577266186SHannes Reinecke 	return status;
34677266186SHannes Reinecke }
34777266186SHannes Reinecke 
34877266186SHannes Reinecke /**
34977266186SHannes Reinecke  * myrs_dev_op - executes a "Device Operation" Command
35077266186SHannes Reinecke  */
35177266186SHannes Reinecke static unsigned char myrs_dev_op(struct myrs_hba *cs,
35277266186SHannes Reinecke 		enum myrs_ioctl_opcode opcode, enum myrs_opdev opdev)
35377266186SHannes Reinecke {
35477266186SHannes Reinecke 	struct myrs_cmdblk *cmd_blk = &cs->dcmd_blk;
35577266186SHannes Reinecke 	union myrs_cmd_mbox *mbox = &cmd_blk->mbox;
35677266186SHannes Reinecke 	unsigned char status;
35777266186SHannes Reinecke 
35877266186SHannes Reinecke 	mutex_lock(&cs->dcmd_mutex);
35977266186SHannes Reinecke 	myrs_reset_cmd(cmd_blk);
36077266186SHannes Reinecke 	mbox->dev_op.opcode = MYRS_CMD_OP_IOCTL;
36177266186SHannes Reinecke 	mbox->dev_op.id = MYRS_DCMD_TAG;
36277266186SHannes Reinecke 	mbox->dev_op.control.dma_ctrl_to_host = true;
36377266186SHannes Reinecke 	mbox->dev_op.control.no_autosense = true;
36477266186SHannes Reinecke 	mbox->dev_op.ioctl_opcode = opcode;
36577266186SHannes Reinecke 	mbox->dev_op.opdev = opdev;
36677266186SHannes Reinecke 	myrs_exec_cmd(cs, cmd_blk);
36777266186SHannes Reinecke 	status = cmd_blk->status;
36877266186SHannes Reinecke 	mutex_unlock(&cs->dcmd_mutex);
36977266186SHannes Reinecke 	return status;
37077266186SHannes Reinecke }
37177266186SHannes Reinecke 
37277266186SHannes Reinecke /**
37377266186SHannes Reinecke  * myrs_translate_pdev - translates a Physical Device Channel and
37477266186SHannes Reinecke  * TargetID into a Logical Device.
37577266186SHannes Reinecke  */
37677266186SHannes Reinecke static unsigned char myrs_translate_pdev(struct myrs_hba *cs,
37777266186SHannes Reinecke 		unsigned char channel, unsigned char target, unsigned char lun,
37877266186SHannes Reinecke 		struct myrs_devmap *devmap)
37977266186SHannes Reinecke {
38077266186SHannes Reinecke 	struct pci_dev *pdev = cs->pdev;
38177266186SHannes Reinecke 	dma_addr_t devmap_addr;
38277266186SHannes Reinecke 	struct myrs_cmdblk *cmd_blk;
38377266186SHannes Reinecke 	union myrs_cmd_mbox *mbox;
38477266186SHannes Reinecke 	union myrs_sgl *sgl;
38577266186SHannes Reinecke 	unsigned char status;
38677266186SHannes Reinecke 
38777266186SHannes Reinecke 	memset(devmap, 0x0, sizeof(struct myrs_devmap));
38877266186SHannes Reinecke 	devmap_addr = dma_map_single(&pdev->dev, devmap,
38977266186SHannes Reinecke 				     sizeof(struct myrs_devmap),
39077266186SHannes Reinecke 				     DMA_FROM_DEVICE);
39177266186SHannes Reinecke 	if (dma_mapping_error(&pdev->dev, devmap_addr))
39277266186SHannes Reinecke 		return MYRS_STATUS_FAILED;
39377266186SHannes Reinecke 
39477266186SHannes Reinecke 	mutex_lock(&cs->dcmd_mutex);
39577266186SHannes Reinecke 	cmd_blk = &cs->dcmd_blk;
39677266186SHannes Reinecke 	mbox = &cmd_blk->mbox;
39777266186SHannes Reinecke 	mbox->pdev_info.opcode = MYRS_CMD_OP_IOCTL;
39877266186SHannes Reinecke 	mbox->pdev_info.control.dma_ctrl_to_host = true;
39977266186SHannes Reinecke 	mbox->pdev_info.control.no_autosense = true;
40077266186SHannes Reinecke 	mbox->pdev_info.dma_size = sizeof(struct myrs_devmap);
40177266186SHannes Reinecke 	mbox->pdev_info.pdev.target = target;
40277266186SHannes Reinecke 	mbox->pdev_info.pdev.channel = channel;
40377266186SHannes Reinecke 	mbox->pdev_info.pdev.lun = lun;
40477266186SHannes Reinecke 	mbox->pdev_info.ioctl_opcode = MYRS_IOCTL_XLATE_PDEV_TO_LDEV;
40577266186SHannes Reinecke 	sgl = &mbox->pdev_info.dma_addr;
40677266186SHannes Reinecke 	sgl->sge[0].sge_addr = devmap_addr;
40777266186SHannes Reinecke 	sgl->sge[0].sge_count = mbox->pdev_info.dma_size;
40877266186SHannes Reinecke 
40977266186SHannes Reinecke 	myrs_exec_cmd(cs, cmd_blk);
41077266186SHannes Reinecke 	status = cmd_blk->status;
41177266186SHannes Reinecke 	mutex_unlock(&cs->dcmd_mutex);
41277266186SHannes Reinecke 	dma_unmap_single(&pdev->dev, devmap_addr,
41377266186SHannes Reinecke 			 sizeof(struct myrs_devmap), DMA_FROM_DEVICE);
41477266186SHannes Reinecke 	return status;
41577266186SHannes Reinecke }
41677266186SHannes Reinecke 
41777266186SHannes Reinecke /**
41877266186SHannes Reinecke  * myrs_get_event - executes a Get Event Command
41977266186SHannes Reinecke  */
42077266186SHannes Reinecke static unsigned char myrs_get_event(struct myrs_hba *cs,
42177266186SHannes Reinecke 		unsigned int event_num, struct myrs_event *event_buf)
42277266186SHannes Reinecke {
42377266186SHannes Reinecke 	struct pci_dev *pdev = cs->pdev;
42477266186SHannes Reinecke 	dma_addr_t event_addr;
42577266186SHannes Reinecke 	struct myrs_cmdblk *cmd_blk = &cs->mcmd_blk;
42677266186SHannes Reinecke 	union myrs_cmd_mbox *mbox = &cmd_blk->mbox;
42777266186SHannes Reinecke 	union myrs_sgl *sgl;
42877266186SHannes Reinecke 	unsigned char status;
42977266186SHannes Reinecke 
43077266186SHannes Reinecke 	event_addr = dma_map_single(&pdev->dev, event_buf,
43177266186SHannes Reinecke 				    sizeof(struct myrs_event), DMA_FROM_DEVICE);
43277266186SHannes Reinecke 	if (dma_mapping_error(&pdev->dev, event_addr))
43377266186SHannes Reinecke 		return MYRS_STATUS_FAILED;
43477266186SHannes Reinecke 
43577266186SHannes Reinecke 	mbox->get_event.opcode = MYRS_CMD_OP_IOCTL;
43677266186SHannes Reinecke 	mbox->get_event.dma_size = sizeof(struct myrs_event);
43777266186SHannes Reinecke 	mbox->get_event.evnum_upper = event_num >> 16;
43877266186SHannes Reinecke 	mbox->get_event.ctlr_num = 0;
43977266186SHannes Reinecke 	mbox->get_event.ioctl_opcode = MYRS_IOCTL_GET_EVENT;
44077266186SHannes Reinecke 	mbox->get_event.evnum_lower = event_num & 0xFFFF;
44177266186SHannes Reinecke 	sgl = &mbox->get_event.dma_addr;
44277266186SHannes Reinecke 	sgl->sge[0].sge_addr = event_addr;
44377266186SHannes Reinecke 	sgl->sge[0].sge_count = mbox->get_event.dma_size;
44477266186SHannes Reinecke 	myrs_exec_cmd(cs, cmd_blk);
44577266186SHannes Reinecke 	status = cmd_blk->status;
44677266186SHannes Reinecke 	dma_unmap_single(&pdev->dev, event_addr,
44777266186SHannes Reinecke 			 sizeof(struct myrs_event), DMA_FROM_DEVICE);
44877266186SHannes Reinecke 
44977266186SHannes Reinecke 	return status;
45077266186SHannes Reinecke }
45177266186SHannes Reinecke 
45277266186SHannes Reinecke /*
45377266186SHannes Reinecke  * myrs_get_fwstatus - executes a Get Health Status Command
45477266186SHannes Reinecke  */
45577266186SHannes Reinecke static unsigned char myrs_get_fwstatus(struct myrs_hba *cs)
45677266186SHannes Reinecke {
45777266186SHannes Reinecke 	struct myrs_cmdblk *cmd_blk = &cs->mcmd_blk;
45877266186SHannes Reinecke 	union myrs_cmd_mbox *mbox = &cmd_blk->mbox;
45977266186SHannes Reinecke 	union myrs_sgl *sgl;
46077266186SHannes Reinecke 	unsigned char status = cmd_blk->status;
46177266186SHannes Reinecke 
46277266186SHannes Reinecke 	myrs_reset_cmd(cmd_blk);
46377266186SHannes Reinecke 	mbox->common.opcode = MYRS_CMD_OP_IOCTL;
46477266186SHannes Reinecke 	mbox->common.id = MYRS_MCMD_TAG;
46577266186SHannes Reinecke 	mbox->common.control.dma_ctrl_to_host = true;
46677266186SHannes Reinecke 	mbox->common.control.no_autosense = true;
46777266186SHannes Reinecke 	mbox->common.dma_size = sizeof(struct myrs_fwstat);
46877266186SHannes Reinecke 	mbox->common.ioctl_opcode = MYRS_IOCTL_GET_HEALTH_STATUS;
46977266186SHannes Reinecke 	sgl = &mbox->common.dma_addr;
47077266186SHannes Reinecke 	sgl->sge[0].sge_addr = cs->fwstat_addr;
47177266186SHannes Reinecke 	sgl->sge[0].sge_count = mbox->ctlr_info.dma_size;
47277266186SHannes Reinecke 	dev_dbg(&cs->host->shost_gendev, "Sending GetHealthStatus\n");
47377266186SHannes Reinecke 	myrs_exec_cmd(cs, cmd_blk);
47477266186SHannes Reinecke 	status = cmd_blk->status;
47577266186SHannes Reinecke 
47677266186SHannes Reinecke 	return status;
47777266186SHannes Reinecke }
47877266186SHannes Reinecke 
47977266186SHannes Reinecke /**
48077266186SHannes Reinecke  * myrs_enable_mmio_mbox - enables the Memory Mailbox Interface
48177266186SHannes Reinecke  */
48277266186SHannes Reinecke static bool myrs_enable_mmio_mbox(struct myrs_hba *cs,
48377266186SHannes Reinecke 		enable_mbox_t enable_mbox_fn)
48477266186SHannes Reinecke {
48577266186SHannes Reinecke 	void __iomem *base = cs->io_base;
48677266186SHannes Reinecke 	struct pci_dev *pdev = cs->pdev;
48777266186SHannes Reinecke 	union myrs_cmd_mbox *cmd_mbox;
48877266186SHannes Reinecke 	struct myrs_stat_mbox *stat_mbox;
48977266186SHannes Reinecke 	union myrs_cmd_mbox *mbox;
49077266186SHannes Reinecke 	dma_addr_t mbox_addr;
49177266186SHannes Reinecke 	unsigned char status = MYRS_STATUS_FAILED;
49277266186SHannes Reinecke 
49377266186SHannes Reinecke 	if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)))
49477266186SHannes Reinecke 		if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32))) {
49577266186SHannes Reinecke 			dev_err(&pdev->dev, "DMA mask out of range\n");
49677266186SHannes Reinecke 			return false;
49777266186SHannes Reinecke 		}
49877266186SHannes Reinecke 
49977266186SHannes Reinecke 	/* Temporary dma mapping, used only in the scope of this function */
50077266186SHannes Reinecke 	mbox = dma_alloc_coherent(&pdev->dev, sizeof(union myrs_cmd_mbox),
50177266186SHannes Reinecke 				  &mbox_addr, GFP_KERNEL);
50277266186SHannes Reinecke 	if (dma_mapping_error(&pdev->dev, mbox_addr))
50377266186SHannes Reinecke 		return false;
50477266186SHannes Reinecke 
50577266186SHannes Reinecke 	/* These are the base addresses for the command memory mailbox array */
50677266186SHannes Reinecke 	cs->cmd_mbox_size = MYRS_MAX_CMD_MBOX * sizeof(union myrs_cmd_mbox);
50777266186SHannes Reinecke 	cmd_mbox = dma_alloc_coherent(&pdev->dev, cs->cmd_mbox_size,
50877266186SHannes Reinecke 				      &cs->cmd_mbox_addr, GFP_KERNEL);
50977266186SHannes Reinecke 	if (dma_mapping_error(&pdev->dev, cs->cmd_mbox_addr)) {
51077266186SHannes Reinecke 		dev_err(&pdev->dev, "Failed to map command mailbox\n");
51177266186SHannes Reinecke 		goto out_free;
51277266186SHannes Reinecke 	}
51377266186SHannes Reinecke 	cs->first_cmd_mbox = cmd_mbox;
51477266186SHannes Reinecke 	cmd_mbox += MYRS_MAX_CMD_MBOX - 1;
51577266186SHannes Reinecke 	cs->last_cmd_mbox = cmd_mbox;
51677266186SHannes Reinecke 	cs->next_cmd_mbox = cs->first_cmd_mbox;
51777266186SHannes Reinecke 	cs->prev_cmd_mbox1 = cs->last_cmd_mbox;
51877266186SHannes Reinecke 	cs->prev_cmd_mbox2 = cs->last_cmd_mbox - 1;
51977266186SHannes Reinecke 
52077266186SHannes Reinecke 	/* These are the base addresses for the status memory mailbox array */
52177266186SHannes Reinecke 	cs->stat_mbox_size = MYRS_MAX_STAT_MBOX * sizeof(struct myrs_stat_mbox);
52277266186SHannes Reinecke 	stat_mbox = dma_alloc_coherent(&pdev->dev, cs->stat_mbox_size,
52377266186SHannes Reinecke 				       &cs->stat_mbox_addr, GFP_KERNEL);
52477266186SHannes Reinecke 	if (dma_mapping_error(&pdev->dev, cs->stat_mbox_addr)) {
52577266186SHannes Reinecke 		dev_err(&pdev->dev, "Failed to map status mailbox\n");
52677266186SHannes Reinecke 		goto out_free;
52777266186SHannes Reinecke 	}
52877266186SHannes Reinecke 
52977266186SHannes Reinecke 	cs->first_stat_mbox = stat_mbox;
53077266186SHannes Reinecke 	stat_mbox += MYRS_MAX_STAT_MBOX - 1;
53177266186SHannes Reinecke 	cs->last_stat_mbox = stat_mbox;
53277266186SHannes Reinecke 	cs->next_stat_mbox = cs->first_stat_mbox;
53377266186SHannes Reinecke 
53477266186SHannes Reinecke 	cs->fwstat_buf = dma_alloc_coherent(&pdev->dev,
53577266186SHannes Reinecke 					    sizeof(struct myrs_fwstat),
53677266186SHannes Reinecke 					    &cs->fwstat_addr, GFP_KERNEL);
53777266186SHannes Reinecke 	if (dma_mapping_error(&pdev->dev, cs->fwstat_addr)) {
53877266186SHannes Reinecke 		dev_err(&pdev->dev, "Failed to map firmware health buffer\n");
53977266186SHannes Reinecke 		cs->fwstat_buf = NULL;
54077266186SHannes Reinecke 		goto out_free;
54177266186SHannes Reinecke 	}
54277266186SHannes Reinecke 	cs->ctlr_info = kzalloc(sizeof(struct myrs_ctlr_info),
54377266186SHannes Reinecke 				GFP_KERNEL | GFP_DMA);
54477266186SHannes Reinecke 	if (!cs->ctlr_info)
54577266186SHannes Reinecke 		goto out_free;
54677266186SHannes Reinecke 
54777266186SHannes Reinecke 	cs->event_buf = kzalloc(sizeof(struct myrs_event),
54877266186SHannes Reinecke 				GFP_KERNEL | GFP_DMA);
54977266186SHannes Reinecke 	if (!cs->event_buf)
55077266186SHannes Reinecke 		goto out_free;
55177266186SHannes Reinecke 
55277266186SHannes Reinecke 	/* Enable the Memory Mailbox Interface. */
55377266186SHannes Reinecke 	memset(mbox, 0, sizeof(union myrs_cmd_mbox));
55477266186SHannes Reinecke 	mbox->set_mbox.id = 1;
55577266186SHannes Reinecke 	mbox->set_mbox.opcode = MYRS_CMD_OP_IOCTL;
55677266186SHannes Reinecke 	mbox->set_mbox.control.no_autosense = true;
55777266186SHannes Reinecke 	mbox->set_mbox.first_cmd_mbox_size_kb =
55877266186SHannes Reinecke 		(MYRS_MAX_CMD_MBOX * sizeof(union myrs_cmd_mbox)) >> 10;
55977266186SHannes Reinecke 	mbox->set_mbox.first_stat_mbox_size_kb =
56077266186SHannes Reinecke 		(MYRS_MAX_STAT_MBOX * sizeof(struct myrs_stat_mbox)) >> 10;
56177266186SHannes Reinecke 	mbox->set_mbox.second_cmd_mbox_size_kb = 0;
56277266186SHannes Reinecke 	mbox->set_mbox.second_stat_mbox_size_kb = 0;
56377266186SHannes Reinecke 	mbox->set_mbox.sense_len = 0;
56477266186SHannes Reinecke 	mbox->set_mbox.ioctl_opcode = MYRS_IOCTL_SET_MEM_MBOX;
56577266186SHannes Reinecke 	mbox->set_mbox.fwstat_buf_size_kb = 1;
56677266186SHannes Reinecke 	mbox->set_mbox.fwstat_buf_addr = cs->fwstat_addr;
56777266186SHannes Reinecke 	mbox->set_mbox.first_cmd_mbox_addr = cs->cmd_mbox_addr;
56877266186SHannes Reinecke 	mbox->set_mbox.first_stat_mbox_addr = cs->stat_mbox_addr;
56977266186SHannes Reinecke 	status = enable_mbox_fn(base, mbox_addr);
57077266186SHannes Reinecke 
57177266186SHannes Reinecke out_free:
57277266186SHannes Reinecke 	dma_free_coherent(&pdev->dev, sizeof(union myrs_cmd_mbox),
57377266186SHannes Reinecke 			  mbox, mbox_addr);
57477266186SHannes Reinecke 	if (status != MYRS_STATUS_SUCCESS)
57577266186SHannes Reinecke 		dev_err(&pdev->dev, "Failed to enable mailbox, status %X\n",
57677266186SHannes Reinecke 			status);
57777266186SHannes Reinecke 	return (status == MYRS_STATUS_SUCCESS);
57877266186SHannes Reinecke }
57977266186SHannes Reinecke 
58077266186SHannes Reinecke /**
58177266186SHannes Reinecke  * myrs_get_config - reads the Configuration Information
58277266186SHannes Reinecke  */
58377266186SHannes Reinecke static int myrs_get_config(struct myrs_hba *cs)
58477266186SHannes Reinecke {
58577266186SHannes Reinecke 	struct myrs_ctlr_info *info = cs->ctlr_info;
58677266186SHannes Reinecke 	struct Scsi_Host *shost = cs->host;
58777266186SHannes Reinecke 	unsigned char status;
58877266186SHannes Reinecke 	unsigned char model[20];
58977266186SHannes Reinecke 	unsigned char fw_version[12];
59077266186SHannes Reinecke 	int i, model_len;
59177266186SHannes Reinecke 
59277266186SHannes Reinecke 	/* Get data into dma-able area, then copy into permanent location */
59377266186SHannes Reinecke 	mutex_lock(&cs->cinfo_mutex);
59477266186SHannes Reinecke 	status = myrs_get_ctlr_info(cs);
59577266186SHannes Reinecke 	mutex_unlock(&cs->cinfo_mutex);
59677266186SHannes Reinecke 	if (status != MYRS_STATUS_SUCCESS) {
59777266186SHannes Reinecke 		shost_printk(KERN_ERR, shost,
59877266186SHannes Reinecke 			     "Failed to get controller information\n");
59977266186SHannes Reinecke 		return -ENODEV;
60077266186SHannes Reinecke 	}
60177266186SHannes Reinecke 
60277266186SHannes Reinecke 	/* Initialize the Controller Model Name and Full Model Name fields. */
60377266186SHannes Reinecke 	model_len = sizeof(info->ctlr_name);
60477266186SHannes Reinecke 	if (model_len > sizeof(model)-1)
60577266186SHannes Reinecke 		model_len = sizeof(model)-1;
60677266186SHannes Reinecke 	memcpy(model, info->ctlr_name, model_len);
60777266186SHannes Reinecke 	model_len--;
60877266186SHannes Reinecke 	while (model[model_len] == ' ' || model[model_len] == '\0')
60977266186SHannes Reinecke 		model_len--;
61077266186SHannes Reinecke 	model[++model_len] = '\0';
61177266186SHannes Reinecke 	strcpy(cs->model_name, "DAC960 ");
61277266186SHannes Reinecke 	strcat(cs->model_name, model);
61377266186SHannes Reinecke 	/* Initialize the Controller Firmware Version field. */
61477266186SHannes Reinecke 	sprintf(fw_version, "%d.%02d-%02d",
61577266186SHannes Reinecke 		info->fw_major_version, info->fw_minor_version,
61677266186SHannes Reinecke 		info->fw_turn_number);
61777266186SHannes Reinecke 	if (info->fw_major_version == 6 &&
61877266186SHannes Reinecke 	    info->fw_minor_version == 0 &&
61977266186SHannes Reinecke 	    info->fw_turn_number < 1) {
62077266186SHannes Reinecke 		shost_printk(KERN_WARNING, shost,
62177266186SHannes Reinecke 			"FIRMWARE VERSION %s DOES NOT PROVIDE THE CONTROLLER\n"
62277266186SHannes Reinecke 			"STATUS MONITORING FUNCTIONALITY NEEDED BY THIS DRIVER.\n"
62377266186SHannes Reinecke 			"PLEASE UPGRADE TO VERSION 6.00-01 OR ABOVE.\n",
62477266186SHannes Reinecke 			fw_version);
62577266186SHannes Reinecke 		return -ENODEV;
62677266186SHannes Reinecke 	}
62777266186SHannes Reinecke 	/* Initialize the Controller Channels and Targets. */
62877266186SHannes Reinecke 	shost->max_channel = info->physchan_present + info->virtchan_present;
62977266186SHannes Reinecke 	shost->max_id = info->max_targets[0];
63077266186SHannes Reinecke 	for (i = 1; i < 16; i++) {
63177266186SHannes Reinecke 		if (!info->max_targets[i])
63277266186SHannes Reinecke 			continue;
63377266186SHannes Reinecke 		if (shost->max_id < info->max_targets[i])
63477266186SHannes Reinecke 			shost->max_id = info->max_targets[i];
63577266186SHannes Reinecke 	}
63677266186SHannes Reinecke 
63777266186SHannes Reinecke 	/*
63877266186SHannes Reinecke 	 * Initialize the Controller Queue Depth, Driver Queue Depth,
63977266186SHannes Reinecke 	 * Logical Drive Count, Maximum Blocks per Command, Controller
64077266186SHannes Reinecke 	 * Scatter/Gather Limit, and Driver Scatter/Gather Limit.
64177266186SHannes Reinecke 	 * The Driver Queue Depth must be at most three less than
64277266186SHannes Reinecke 	 * the Controller Queue Depth; tag '1' is reserved for
64377266186SHannes Reinecke 	 * direct commands, and tag '2' for monitoring commands.
64477266186SHannes Reinecke 	 */
64577266186SHannes Reinecke 	shost->can_queue = info->max_tcq - 3;
64677266186SHannes Reinecke 	if (shost->can_queue > MYRS_MAX_CMD_MBOX - 3)
64777266186SHannes Reinecke 		shost->can_queue = MYRS_MAX_CMD_MBOX - 3;
64877266186SHannes Reinecke 	shost->max_sectors = info->max_transfer_size;
64977266186SHannes Reinecke 	shost->sg_tablesize = info->max_sge;
65077266186SHannes Reinecke 	if (shost->sg_tablesize > MYRS_SG_LIMIT)
65177266186SHannes Reinecke 		shost->sg_tablesize = MYRS_SG_LIMIT;
65277266186SHannes Reinecke 
65377266186SHannes Reinecke 	shost_printk(KERN_INFO, shost,
65477266186SHannes Reinecke 		"Configuring %s PCI RAID Controller\n", model);
65577266186SHannes Reinecke 	shost_printk(KERN_INFO, shost,
65677266186SHannes Reinecke 		"  Firmware Version: %s, Channels: %d, Memory Size: %dMB\n",
65777266186SHannes Reinecke 		fw_version, info->physchan_present, info->mem_size_mb);
65877266186SHannes Reinecke 
65977266186SHannes Reinecke 	shost_printk(KERN_INFO, shost,
66077266186SHannes Reinecke 		     "  Controller Queue Depth: %d, Maximum Blocks per Command: %d\n",
66177266186SHannes Reinecke 		     shost->can_queue, shost->max_sectors);
66277266186SHannes Reinecke 
66377266186SHannes Reinecke 	shost_printk(KERN_INFO, shost,
66477266186SHannes Reinecke 		     "  Driver Queue Depth: %d, Scatter/Gather Limit: %d of %d Segments\n",
66577266186SHannes Reinecke 		     shost->can_queue, shost->sg_tablesize, MYRS_SG_LIMIT);
66677266186SHannes Reinecke 	for (i = 0; i < info->physchan_max; i++) {
66777266186SHannes Reinecke 		if (!info->max_targets[i])
66877266186SHannes Reinecke 			continue;
66977266186SHannes Reinecke 		shost_printk(KERN_INFO, shost,
67077266186SHannes Reinecke 			     "  Device Channel %d: max %d devices\n",
67177266186SHannes Reinecke 			     i, info->max_targets[i]);
67277266186SHannes Reinecke 	}
67377266186SHannes Reinecke 	shost_printk(KERN_INFO, shost,
67477266186SHannes Reinecke 		     "  Physical: %d/%d channels, %d disks, %d devices\n",
67577266186SHannes Reinecke 		     info->physchan_present, info->physchan_max,
67677266186SHannes Reinecke 		     info->pdisk_present, info->pdev_present);
67777266186SHannes Reinecke 
67877266186SHannes Reinecke 	shost_printk(KERN_INFO, shost,
67977266186SHannes Reinecke 		     "  Logical: %d/%d channels, %d disks\n",
68077266186SHannes Reinecke 		     info->virtchan_present, info->virtchan_max,
68177266186SHannes Reinecke 		     info->ldev_present);
68277266186SHannes Reinecke 	return 0;
68377266186SHannes Reinecke }
68477266186SHannes Reinecke 
68577266186SHannes Reinecke /**
68677266186SHannes Reinecke  * myrs_log_event - prints a Controller Event message
68777266186SHannes Reinecke  */
68877266186SHannes Reinecke static struct {
68977266186SHannes Reinecke 	int ev_code;
69077266186SHannes Reinecke 	unsigned char *ev_msg;
69177266186SHannes Reinecke } myrs_ev_list[] = {
69277266186SHannes Reinecke 	/* Physical Device Events (0x0000 - 0x007F) */
69377266186SHannes Reinecke 	{ 0x0001, "P Online" },
69477266186SHannes Reinecke 	{ 0x0002, "P Standby" },
69577266186SHannes Reinecke 	{ 0x0005, "P Automatic Rebuild Started" },
69677266186SHannes Reinecke 	{ 0x0006, "P Manual Rebuild Started" },
69777266186SHannes Reinecke 	{ 0x0007, "P Rebuild Completed" },
69877266186SHannes Reinecke 	{ 0x0008, "P Rebuild Cancelled" },
69977266186SHannes Reinecke 	{ 0x0009, "P Rebuild Failed for Unknown Reasons" },
70077266186SHannes Reinecke 	{ 0x000A, "P Rebuild Failed due to New Physical Device" },
70177266186SHannes Reinecke 	{ 0x000B, "P Rebuild Failed due to Logical Drive Failure" },
70277266186SHannes Reinecke 	{ 0x000C, "S Offline" },
70377266186SHannes Reinecke 	{ 0x000D, "P Found" },
70477266186SHannes Reinecke 	{ 0x000E, "P Removed" },
70577266186SHannes Reinecke 	{ 0x000F, "P Unconfigured" },
70677266186SHannes Reinecke 	{ 0x0010, "P Expand Capacity Started" },
70777266186SHannes Reinecke 	{ 0x0011, "P Expand Capacity Completed" },
70877266186SHannes Reinecke 	{ 0x0012, "P Expand Capacity Failed" },
70977266186SHannes Reinecke 	{ 0x0013, "P Command Timed Out" },
71077266186SHannes Reinecke 	{ 0x0014, "P Command Aborted" },
71177266186SHannes Reinecke 	{ 0x0015, "P Command Retried" },
71277266186SHannes Reinecke 	{ 0x0016, "P Parity Error" },
71377266186SHannes Reinecke 	{ 0x0017, "P Soft Error" },
71477266186SHannes Reinecke 	{ 0x0018, "P Miscellaneous Error" },
71577266186SHannes Reinecke 	{ 0x0019, "P Reset" },
71677266186SHannes Reinecke 	{ 0x001A, "P Active Spare Found" },
71777266186SHannes Reinecke 	{ 0x001B, "P Warm Spare Found" },
71877266186SHannes Reinecke 	{ 0x001C, "S Sense Data Received" },
71977266186SHannes Reinecke 	{ 0x001D, "P Initialization Started" },
72077266186SHannes Reinecke 	{ 0x001E, "P Initialization Completed" },
72177266186SHannes Reinecke 	{ 0x001F, "P Initialization Failed" },
72277266186SHannes Reinecke 	{ 0x0020, "P Initialization Cancelled" },
72377266186SHannes Reinecke 	{ 0x0021, "P Failed because Write Recovery Failed" },
72477266186SHannes Reinecke 	{ 0x0022, "P Failed because SCSI Bus Reset Failed" },
72577266186SHannes Reinecke 	{ 0x0023, "P Failed because of Double Check Condition" },
72677266186SHannes Reinecke 	{ 0x0024, "P Failed because Device Cannot Be Accessed" },
72777266186SHannes Reinecke 	{ 0x0025, "P Failed because of Gross Error on SCSI Processor" },
72877266186SHannes Reinecke 	{ 0x0026, "P Failed because of Bad Tag from Device" },
72977266186SHannes Reinecke 	{ 0x0027, "P Failed because of Command Timeout" },
73077266186SHannes Reinecke 	{ 0x0028, "P Failed because of System Reset" },
73177266186SHannes Reinecke 	{ 0x0029, "P Failed because of Busy Status or Parity Error" },
73277266186SHannes Reinecke 	{ 0x002A, "P Failed because Host Set Device to Failed State" },
73377266186SHannes Reinecke 	{ 0x002B, "P Failed because of Selection Timeout" },
73477266186SHannes Reinecke 	{ 0x002C, "P Failed because of SCSI Bus Phase Error" },
73577266186SHannes Reinecke 	{ 0x002D, "P Failed because Device Returned Unknown Status" },
73677266186SHannes Reinecke 	{ 0x002E, "P Failed because Device Not Ready" },
73777266186SHannes Reinecke 	{ 0x002F, "P Failed because Device Not Found at Startup" },
73877266186SHannes Reinecke 	{ 0x0030, "P Failed because COD Write Operation Failed" },
73977266186SHannes Reinecke 	{ 0x0031, "P Failed because BDT Write Operation Failed" },
74077266186SHannes Reinecke 	{ 0x0039, "P Missing at Startup" },
74177266186SHannes Reinecke 	{ 0x003A, "P Start Rebuild Failed due to Physical Drive Too Small" },
74277266186SHannes Reinecke 	{ 0x003C, "P Temporarily Offline Device Automatically Made Online" },
74377266186SHannes Reinecke 	{ 0x003D, "P Standby Rebuild Started" },
74477266186SHannes Reinecke 	/* Logical Device Events (0x0080 - 0x00FF) */
74577266186SHannes Reinecke 	{ 0x0080, "M Consistency Check Started" },
74677266186SHannes Reinecke 	{ 0x0081, "M Consistency Check Completed" },
74777266186SHannes Reinecke 	{ 0x0082, "M Consistency Check Cancelled" },
74877266186SHannes Reinecke 	{ 0x0083, "M Consistency Check Completed With Errors" },
74977266186SHannes Reinecke 	{ 0x0084, "M Consistency Check Failed due to Logical Drive Failure" },
75077266186SHannes Reinecke 	{ 0x0085, "M Consistency Check Failed due to Physical Device Failure" },
75177266186SHannes Reinecke 	{ 0x0086, "L Offline" },
75277266186SHannes Reinecke 	{ 0x0087, "L Critical" },
75377266186SHannes Reinecke 	{ 0x0088, "L Online" },
75477266186SHannes Reinecke 	{ 0x0089, "M Automatic Rebuild Started" },
75577266186SHannes Reinecke 	{ 0x008A, "M Manual Rebuild Started" },
75677266186SHannes Reinecke 	{ 0x008B, "M Rebuild Completed" },
75777266186SHannes Reinecke 	{ 0x008C, "M Rebuild Cancelled" },
75877266186SHannes Reinecke 	{ 0x008D, "M Rebuild Failed for Unknown Reasons" },
75977266186SHannes Reinecke 	{ 0x008E, "M Rebuild Failed due to New Physical Device" },
76077266186SHannes Reinecke 	{ 0x008F, "M Rebuild Failed due to Logical Drive Failure" },
76177266186SHannes Reinecke 	{ 0x0090, "M Initialization Started" },
76277266186SHannes Reinecke 	{ 0x0091, "M Initialization Completed" },
76377266186SHannes Reinecke 	{ 0x0092, "M Initialization Cancelled" },
76477266186SHannes Reinecke 	{ 0x0093, "M Initialization Failed" },
76577266186SHannes Reinecke 	{ 0x0094, "L Found" },
76677266186SHannes Reinecke 	{ 0x0095, "L Deleted" },
76777266186SHannes Reinecke 	{ 0x0096, "M Expand Capacity Started" },
76877266186SHannes Reinecke 	{ 0x0097, "M Expand Capacity Completed" },
76977266186SHannes Reinecke 	{ 0x0098, "M Expand Capacity Failed" },
77077266186SHannes Reinecke 	{ 0x0099, "L Bad Block Found" },
77177266186SHannes Reinecke 	{ 0x009A, "L Size Changed" },
77277266186SHannes Reinecke 	{ 0x009B, "L Type Changed" },
77377266186SHannes Reinecke 	{ 0x009C, "L Bad Data Block Found" },
77477266186SHannes Reinecke 	{ 0x009E, "L Read of Data Block in BDT" },
77577266186SHannes Reinecke 	{ 0x009F, "L Write Back Data for Disk Block Lost" },
77677266186SHannes Reinecke 	{ 0x00A0, "L Temporarily Offline RAID-5/3 Drive Made Online" },
77777266186SHannes Reinecke 	{ 0x00A1, "L Temporarily Offline RAID-6/1/0/7 Drive Made Online" },
77877266186SHannes Reinecke 	{ 0x00A2, "L Standby Rebuild Started" },
77977266186SHannes Reinecke 	/* Fault Management Events (0x0100 - 0x017F) */
78077266186SHannes Reinecke 	{ 0x0140, "E Fan %d Failed" },
78177266186SHannes Reinecke 	{ 0x0141, "E Fan %d OK" },
78277266186SHannes Reinecke 	{ 0x0142, "E Fan %d Not Present" },
78377266186SHannes Reinecke 	{ 0x0143, "E Power Supply %d Failed" },
78477266186SHannes Reinecke 	{ 0x0144, "E Power Supply %d OK" },
78577266186SHannes Reinecke 	{ 0x0145, "E Power Supply %d Not Present" },
78677266186SHannes Reinecke 	{ 0x0146, "E Temperature Sensor %d Temperature Exceeds Safe Limit" },
78777266186SHannes Reinecke 	{ 0x0147, "E Temperature Sensor %d Temperature Exceeds Working Limit" },
78877266186SHannes Reinecke 	{ 0x0148, "E Temperature Sensor %d Temperature Normal" },
78977266186SHannes Reinecke 	{ 0x0149, "E Temperature Sensor %d Not Present" },
79077266186SHannes Reinecke 	{ 0x014A, "E Enclosure Management Unit %d Access Critical" },
79177266186SHannes Reinecke 	{ 0x014B, "E Enclosure Management Unit %d Access OK" },
79277266186SHannes Reinecke 	{ 0x014C, "E Enclosure Management Unit %d Access Offline" },
79377266186SHannes Reinecke 	/* Controller Events (0x0180 - 0x01FF) */
79477266186SHannes Reinecke 	{ 0x0181, "C Cache Write Back Error" },
79577266186SHannes Reinecke 	{ 0x0188, "C Battery Backup Unit Found" },
79677266186SHannes Reinecke 	{ 0x0189, "C Battery Backup Unit Charge Level Low" },
79777266186SHannes Reinecke 	{ 0x018A, "C Battery Backup Unit Charge Level OK" },
79877266186SHannes Reinecke 	{ 0x0193, "C Installation Aborted" },
79977266186SHannes Reinecke 	{ 0x0195, "C Battery Backup Unit Physically Removed" },
80077266186SHannes Reinecke 	{ 0x0196, "C Memory Error During Warm Boot" },
80177266186SHannes Reinecke 	{ 0x019E, "C Memory Soft ECC Error Corrected" },
80277266186SHannes Reinecke 	{ 0x019F, "C Memory Hard ECC Error Corrected" },
80377266186SHannes Reinecke 	{ 0x01A2, "C Battery Backup Unit Failed" },
80477266186SHannes Reinecke 	{ 0x01AB, "C Mirror Race Recovery Failed" },
80577266186SHannes Reinecke 	{ 0x01AC, "C Mirror Race on Critical Drive" },
80677266186SHannes Reinecke 	/* Controller Internal Processor Events */
80777266186SHannes Reinecke 	{ 0x0380, "C Internal Controller Hung" },
80877266186SHannes Reinecke 	{ 0x0381, "C Internal Controller Firmware Breakpoint" },
80977266186SHannes Reinecke 	{ 0x0390, "C Internal Controller i960 Processor Specific Error" },
81077266186SHannes Reinecke 	{ 0x03A0, "C Internal Controller StrongARM Processor Specific Error" },
81177266186SHannes Reinecke 	{ 0, "" }
81277266186SHannes Reinecke };
81377266186SHannes Reinecke 
81477266186SHannes Reinecke static void myrs_log_event(struct myrs_hba *cs, struct myrs_event *ev)
81577266186SHannes Reinecke {
81677266186SHannes Reinecke 	unsigned char msg_buf[MYRS_LINE_BUFFER_SIZE];
81777266186SHannes Reinecke 	int ev_idx = 0, ev_code;
81877266186SHannes Reinecke 	unsigned char ev_type, *ev_msg;
81977266186SHannes Reinecke 	struct Scsi_Host *shost = cs->host;
82077266186SHannes Reinecke 	struct scsi_device *sdev;
82141552199SYueHaibing 	struct scsi_sense_hdr sshdr = {0};
82277266186SHannes Reinecke 	unsigned char sense_info[4];
82377266186SHannes Reinecke 	unsigned char cmd_specific[4];
82477266186SHannes Reinecke 
82577266186SHannes Reinecke 	if (ev->ev_code == 0x1C) {
82677266186SHannes Reinecke 		if (!scsi_normalize_sense(ev->sense_data, 40, &sshdr)) {
82777266186SHannes Reinecke 			memset(&sshdr, 0x0, sizeof(sshdr));
82877266186SHannes Reinecke 			memset(sense_info, 0x0, sizeof(sense_info));
82977266186SHannes Reinecke 			memset(cmd_specific, 0x0, sizeof(cmd_specific));
83077266186SHannes Reinecke 		} else {
83177266186SHannes Reinecke 			memcpy(sense_info, &ev->sense_data[3], 4);
83277266186SHannes Reinecke 			memcpy(cmd_specific, &ev->sense_data[7], 4);
83377266186SHannes Reinecke 		}
83477266186SHannes Reinecke 	}
83577266186SHannes Reinecke 	if (sshdr.sense_key == VENDOR_SPECIFIC &&
83677266186SHannes Reinecke 	    (sshdr.asc == 0x80 || sshdr.asc == 0x81))
83777266186SHannes Reinecke 		ev->ev_code = ((sshdr.asc - 0x80) << 8 | sshdr.ascq);
83877266186SHannes Reinecke 	while (true) {
83977266186SHannes Reinecke 		ev_code = myrs_ev_list[ev_idx].ev_code;
84077266186SHannes Reinecke 		if (ev_code == ev->ev_code || ev_code == 0)
84177266186SHannes Reinecke 			break;
84277266186SHannes Reinecke 		ev_idx++;
84377266186SHannes Reinecke 	}
84477266186SHannes Reinecke 	ev_type = myrs_ev_list[ev_idx].ev_msg[0];
84577266186SHannes Reinecke 	ev_msg = &myrs_ev_list[ev_idx].ev_msg[2];
84677266186SHannes Reinecke 	if (ev_code == 0) {
84777266186SHannes Reinecke 		shost_printk(KERN_WARNING, shost,
84877266186SHannes Reinecke 			     "Unknown Controller Event Code %04X\n",
84977266186SHannes Reinecke 			     ev->ev_code);
85077266186SHannes Reinecke 		return;
85177266186SHannes Reinecke 	}
85277266186SHannes Reinecke 	switch (ev_type) {
85377266186SHannes Reinecke 	case 'P':
85477266186SHannes Reinecke 		sdev = scsi_device_lookup(shost, ev->channel,
85577266186SHannes Reinecke 					  ev->target, 0);
85677266186SHannes Reinecke 		sdev_printk(KERN_INFO, sdev, "event %d: Physical Device %s\n",
85777266186SHannes Reinecke 			    ev->ev_seq, ev_msg);
85877266186SHannes Reinecke 		if (sdev && sdev->hostdata &&
85977266186SHannes Reinecke 		    sdev->channel < cs->ctlr_info->physchan_present) {
86077266186SHannes Reinecke 			struct myrs_pdev_info *pdev_info = sdev->hostdata;
86177266186SHannes Reinecke 
86277266186SHannes Reinecke 			switch (ev->ev_code) {
86377266186SHannes Reinecke 			case 0x0001:
86477266186SHannes Reinecke 			case 0x0007:
86577266186SHannes Reinecke 				pdev_info->dev_state = MYRS_DEVICE_ONLINE;
86677266186SHannes Reinecke 				break;
86777266186SHannes Reinecke 			case 0x0002:
86877266186SHannes Reinecke 				pdev_info->dev_state = MYRS_DEVICE_STANDBY;
86977266186SHannes Reinecke 				break;
87077266186SHannes Reinecke 			case 0x000C:
87177266186SHannes Reinecke 				pdev_info->dev_state = MYRS_DEVICE_OFFLINE;
87277266186SHannes Reinecke 				break;
87377266186SHannes Reinecke 			case 0x000E:
87477266186SHannes Reinecke 				pdev_info->dev_state = MYRS_DEVICE_MISSING;
87577266186SHannes Reinecke 				break;
87677266186SHannes Reinecke 			case 0x000F:
87777266186SHannes Reinecke 				pdev_info->dev_state = MYRS_DEVICE_UNCONFIGURED;
87877266186SHannes Reinecke 				break;
87977266186SHannes Reinecke 			}
88077266186SHannes Reinecke 		}
88177266186SHannes Reinecke 		break;
88277266186SHannes Reinecke 	case 'L':
88377266186SHannes Reinecke 		shost_printk(KERN_INFO, shost,
88477266186SHannes Reinecke 			     "event %d: Logical Drive %d %s\n",
88577266186SHannes Reinecke 			     ev->ev_seq, ev->lun, ev_msg);
88677266186SHannes Reinecke 		cs->needs_update = true;
88777266186SHannes Reinecke 		break;
88877266186SHannes Reinecke 	case 'M':
88977266186SHannes Reinecke 		shost_printk(KERN_INFO, shost,
89077266186SHannes Reinecke 			     "event %d: Logical Drive %d %s\n",
89177266186SHannes Reinecke 			     ev->ev_seq, ev->lun, ev_msg);
89277266186SHannes Reinecke 		cs->needs_update = true;
89377266186SHannes Reinecke 		break;
89477266186SHannes Reinecke 	case 'S':
89577266186SHannes Reinecke 		if (sshdr.sense_key == NO_SENSE ||
89677266186SHannes Reinecke 		    (sshdr.sense_key == NOT_READY &&
89777266186SHannes Reinecke 		     sshdr.asc == 0x04 && (sshdr.ascq == 0x01 ||
89877266186SHannes Reinecke 					    sshdr.ascq == 0x02)))
89977266186SHannes Reinecke 			break;
90077266186SHannes Reinecke 		shost_printk(KERN_INFO, shost,
90177266186SHannes Reinecke 			     "event %d: Physical Device %d:%d %s\n",
90277266186SHannes Reinecke 			     ev->ev_seq, ev->channel, ev->target, ev_msg);
90377266186SHannes Reinecke 		shost_printk(KERN_INFO, shost,
90477266186SHannes Reinecke 			     "Physical Device %d:%d Sense Key = %X, ASC = %02X, ASCQ = %02X\n",
90577266186SHannes Reinecke 			     ev->channel, ev->target,
90677266186SHannes Reinecke 			     sshdr.sense_key, sshdr.asc, sshdr.ascq);
90777266186SHannes Reinecke 		shost_printk(KERN_INFO, shost,
90877266186SHannes Reinecke 			     "Physical Device %d:%d Sense Information = %02X%02X%02X%02X %02X%02X%02X%02X\n",
90977266186SHannes Reinecke 			     ev->channel, ev->target,
91077266186SHannes Reinecke 			     sense_info[0], sense_info[1],
91177266186SHannes Reinecke 			     sense_info[2], sense_info[3],
91277266186SHannes Reinecke 			     cmd_specific[0], cmd_specific[1],
91377266186SHannes Reinecke 			     cmd_specific[2], cmd_specific[3]);
91477266186SHannes Reinecke 		break;
91577266186SHannes Reinecke 	case 'E':
91677266186SHannes Reinecke 		if (cs->disable_enc_msg)
91777266186SHannes Reinecke 			break;
91877266186SHannes Reinecke 		sprintf(msg_buf, ev_msg, ev->lun);
91977266186SHannes Reinecke 		shost_printk(KERN_INFO, shost, "event %d: Enclosure %d %s\n",
92077266186SHannes Reinecke 			     ev->ev_seq, ev->target, msg_buf);
92177266186SHannes Reinecke 		break;
92277266186SHannes Reinecke 	case 'C':
92377266186SHannes Reinecke 		shost_printk(KERN_INFO, shost, "event %d: Controller %s\n",
92477266186SHannes Reinecke 			     ev->ev_seq, ev_msg);
92577266186SHannes Reinecke 		break;
92677266186SHannes Reinecke 	default:
92777266186SHannes Reinecke 		shost_printk(KERN_INFO, shost,
92877266186SHannes Reinecke 			     "event %d: Unknown Event Code %04X\n",
92977266186SHannes Reinecke 			     ev->ev_seq, ev->ev_code);
93077266186SHannes Reinecke 		break;
93177266186SHannes Reinecke 	}
93277266186SHannes Reinecke }
93377266186SHannes Reinecke 
93477266186SHannes Reinecke /*
93577266186SHannes Reinecke  * SCSI sysfs interface functions
93677266186SHannes Reinecke  */
93777266186SHannes Reinecke static ssize_t raid_state_show(struct device *dev,
93877266186SHannes Reinecke 		struct device_attribute *attr, char *buf)
93977266186SHannes Reinecke {
94077266186SHannes Reinecke 	struct scsi_device *sdev = to_scsi_device(dev);
94177266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(sdev->host);
94277266186SHannes Reinecke 	int ret;
94377266186SHannes Reinecke 
94477266186SHannes Reinecke 	if (!sdev->hostdata)
94577266186SHannes Reinecke 		return snprintf(buf, 16, "Unknown\n");
94677266186SHannes Reinecke 
94777266186SHannes Reinecke 	if (sdev->channel >= cs->ctlr_info->physchan_present) {
94877266186SHannes Reinecke 		struct myrs_ldev_info *ldev_info = sdev->hostdata;
94977266186SHannes Reinecke 		const char *name;
95077266186SHannes Reinecke 
95177266186SHannes Reinecke 		name = myrs_devstate_name(ldev_info->dev_state);
95277266186SHannes Reinecke 		if (name)
95377266186SHannes Reinecke 			ret = snprintf(buf, 32, "%s\n", name);
95477266186SHannes Reinecke 		else
95577266186SHannes Reinecke 			ret = snprintf(buf, 32, "Invalid (%02X)\n",
95677266186SHannes Reinecke 				       ldev_info->dev_state);
95777266186SHannes Reinecke 	} else {
95877266186SHannes Reinecke 		struct myrs_pdev_info *pdev_info;
95977266186SHannes Reinecke 		const char *name;
96077266186SHannes Reinecke 
96177266186SHannes Reinecke 		pdev_info = sdev->hostdata;
96277266186SHannes Reinecke 		name = myrs_devstate_name(pdev_info->dev_state);
96377266186SHannes Reinecke 		if (name)
96477266186SHannes Reinecke 			ret = snprintf(buf, 32, "%s\n", name);
96577266186SHannes Reinecke 		else
96677266186SHannes Reinecke 			ret = snprintf(buf, 32, "Invalid (%02X)\n",
96777266186SHannes Reinecke 				       pdev_info->dev_state);
96877266186SHannes Reinecke 	}
96977266186SHannes Reinecke 	return ret;
97077266186SHannes Reinecke }
97177266186SHannes Reinecke 
97277266186SHannes Reinecke static ssize_t raid_state_store(struct device *dev,
97377266186SHannes Reinecke 		struct device_attribute *attr, const char *buf, size_t count)
97477266186SHannes Reinecke {
97577266186SHannes Reinecke 	struct scsi_device *sdev = to_scsi_device(dev);
97677266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(sdev->host);
97777266186SHannes Reinecke 	struct myrs_cmdblk *cmd_blk;
97877266186SHannes Reinecke 	union myrs_cmd_mbox *mbox;
97977266186SHannes Reinecke 	enum myrs_devstate new_state;
98077266186SHannes Reinecke 	unsigned short ldev_num;
98177266186SHannes Reinecke 	unsigned char status;
98277266186SHannes Reinecke 
98377266186SHannes Reinecke 	if (!strncmp(buf, "offline", 7) ||
98477266186SHannes Reinecke 	    !strncmp(buf, "kill", 4))
98577266186SHannes Reinecke 		new_state = MYRS_DEVICE_OFFLINE;
98677266186SHannes Reinecke 	else if (!strncmp(buf, "online", 6))
98777266186SHannes Reinecke 		new_state = MYRS_DEVICE_ONLINE;
98877266186SHannes Reinecke 	else if (!strncmp(buf, "standby", 7))
98977266186SHannes Reinecke 		new_state = MYRS_DEVICE_STANDBY;
99077266186SHannes Reinecke 	else
99177266186SHannes Reinecke 		return -EINVAL;
99277266186SHannes Reinecke 
99377266186SHannes Reinecke 	if (sdev->channel < cs->ctlr_info->physchan_present) {
99477266186SHannes Reinecke 		struct myrs_pdev_info *pdev_info = sdev->hostdata;
99577266186SHannes Reinecke 		struct myrs_devmap *pdev_devmap =
99677266186SHannes Reinecke 			(struct myrs_devmap *)&pdev_info->rsvd13;
99777266186SHannes Reinecke 
99877266186SHannes Reinecke 		if (pdev_info->dev_state == new_state) {
99977266186SHannes Reinecke 			sdev_printk(KERN_INFO, sdev,
100077266186SHannes Reinecke 				    "Device already in %s\n",
100177266186SHannes Reinecke 				    myrs_devstate_name(new_state));
100277266186SHannes Reinecke 			return count;
100377266186SHannes Reinecke 		}
100477266186SHannes Reinecke 		status = myrs_translate_pdev(cs, sdev->channel, sdev->id,
100577266186SHannes Reinecke 					     sdev->lun, pdev_devmap);
100677266186SHannes Reinecke 		if (status != MYRS_STATUS_SUCCESS)
100777266186SHannes Reinecke 			return -ENXIO;
100877266186SHannes Reinecke 		ldev_num = pdev_devmap->ldev_num;
100977266186SHannes Reinecke 	} else {
101077266186SHannes Reinecke 		struct myrs_ldev_info *ldev_info = sdev->hostdata;
101177266186SHannes Reinecke 
101277266186SHannes Reinecke 		if (ldev_info->dev_state == new_state) {
101377266186SHannes Reinecke 			sdev_printk(KERN_INFO, sdev,
101477266186SHannes Reinecke 				    "Device already in %s\n",
101577266186SHannes Reinecke 				    myrs_devstate_name(new_state));
101677266186SHannes Reinecke 			return count;
101777266186SHannes Reinecke 		}
101877266186SHannes Reinecke 		ldev_num = ldev_info->ldev_num;
101977266186SHannes Reinecke 	}
102077266186SHannes Reinecke 	mutex_lock(&cs->dcmd_mutex);
102177266186SHannes Reinecke 	cmd_blk = &cs->dcmd_blk;
102277266186SHannes Reinecke 	myrs_reset_cmd(cmd_blk);
102377266186SHannes Reinecke 	mbox = &cmd_blk->mbox;
102477266186SHannes Reinecke 	mbox->common.opcode = MYRS_CMD_OP_IOCTL;
102577266186SHannes Reinecke 	mbox->common.id = MYRS_DCMD_TAG;
102677266186SHannes Reinecke 	mbox->common.control.dma_ctrl_to_host = true;
102777266186SHannes Reinecke 	mbox->common.control.no_autosense = true;
102877266186SHannes Reinecke 	mbox->set_devstate.ioctl_opcode = MYRS_IOCTL_SET_DEVICE_STATE;
102977266186SHannes Reinecke 	mbox->set_devstate.state = new_state;
103077266186SHannes Reinecke 	mbox->set_devstate.ldev.ldev_num = ldev_num;
103177266186SHannes Reinecke 	myrs_exec_cmd(cs, cmd_blk);
103277266186SHannes Reinecke 	status = cmd_blk->status;
103377266186SHannes Reinecke 	mutex_unlock(&cs->dcmd_mutex);
103477266186SHannes Reinecke 	if (status == MYRS_STATUS_SUCCESS) {
103577266186SHannes Reinecke 		if (sdev->channel < cs->ctlr_info->physchan_present) {
103677266186SHannes Reinecke 			struct myrs_pdev_info *pdev_info = sdev->hostdata;
103777266186SHannes Reinecke 
103877266186SHannes Reinecke 			pdev_info->dev_state = new_state;
103977266186SHannes Reinecke 		} else {
104077266186SHannes Reinecke 			struct myrs_ldev_info *ldev_info = sdev->hostdata;
104177266186SHannes Reinecke 
104277266186SHannes Reinecke 			ldev_info->dev_state = new_state;
104377266186SHannes Reinecke 		}
104477266186SHannes Reinecke 		sdev_printk(KERN_INFO, sdev,
104577266186SHannes Reinecke 			    "Set device state to %s\n",
104677266186SHannes Reinecke 			    myrs_devstate_name(new_state));
104777266186SHannes Reinecke 		return count;
104877266186SHannes Reinecke 	}
104977266186SHannes Reinecke 	sdev_printk(KERN_INFO, sdev,
105077266186SHannes Reinecke 		    "Failed to set device state to %s, status 0x%02x\n",
105177266186SHannes Reinecke 		    myrs_devstate_name(new_state), status);
105277266186SHannes Reinecke 	return -EINVAL;
105377266186SHannes Reinecke }
105477266186SHannes Reinecke static DEVICE_ATTR_RW(raid_state);
105577266186SHannes Reinecke 
105677266186SHannes Reinecke static ssize_t raid_level_show(struct device *dev,
105777266186SHannes Reinecke 		struct device_attribute *attr, char *buf)
105877266186SHannes Reinecke {
105977266186SHannes Reinecke 	struct scsi_device *sdev = to_scsi_device(dev);
106077266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(sdev->host);
106177266186SHannes Reinecke 	const char *name = NULL;
106277266186SHannes Reinecke 
106377266186SHannes Reinecke 	if (!sdev->hostdata)
106477266186SHannes Reinecke 		return snprintf(buf, 16, "Unknown\n");
106577266186SHannes Reinecke 
106677266186SHannes Reinecke 	if (sdev->channel >= cs->ctlr_info->physchan_present) {
106777266186SHannes Reinecke 		struct myrs_ldev_info *ldev_info;
106877266186SHannes Reinecke 
106977266186SHannes Reinecke 		ldev_info = sdev->hostdata;
107077266186SHannes Reinecke 		name = myrs_raid_level_name(ldev_info->raid_level);
107177266186SHannes Reinecke 		if (!name)
107277266186SHannes Reinecke 			return snprintf(buf, 32, "Invalid (%02X)\n",
107377266186SHannes Reinecke 					ldev_info->dev_state);
107477266186SHannes Reinecke 
107577266186SHannes Reinecke 	} else
107677266186SHannes Reinecke 		name = myrs_raid_level_name(MYRS_RAID_PHYSICAL);
107777266186SHannes Reinecke 
107877266186SHannes Reinecke 	return snprintf(buf, 32, "%s\n", name);
107977266186SHannes Reinecke }
108077266186SHannes Reinecke static DEVICE_ATTR_RO(raid_level);
108177266186SHannes Reinecke 
108277266186SHannes Reinecke static ssize_t rebuild_show(struct device *dev,
108377266186SHannes Reinecke 		struct device_attribute *attr, char *buf)
108477266186SHannes Reinecke {
108577266186SHannes Reinecke 	struct scsi_device *sdev = to_scsi_device(dev);
108677266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(sdev->host);
108777266186SHannes Reinecke 	struct myrs_ldev_info *ldev_info;
108877266186SHannes Reinecke 	unsigned short ldev_num;
108977266186SHannes Reinecke 	unsigned char status;
109077266186SHannes Reinecke 
109177266186SHannes Reinecke 	if (sdev->channel < cs->ctlr_info->physchan_present)
109277266186SHannes Reinecke 		return snprintf(buf, 32, "physical device - not rebuilding\n");
109377266186SHannes Reinecke 
109477266186SHannes Reinecke 	ldev_info = sdev->hostdata;
109577266186SHannes Reinecke 	ldev_num = ldev_info->ldev_num;
109677266186SHannes Reinecke 	status = myrs_get_ldev_info(cs, ldev_num, ldev_info);
109777266186SHannes Reinecke 	if (status != MYRS_STATUS_SUCCESS) {
109877266186SHannes Reinecke 		sdev_printk(KERN_INFO, sdev,
109977266186SHannes Reinecke 			    "Failed to get device information, status 0x%02x\n",
110077266186SHannes Reinecke 			    status);
110177266186SHannes Reinecke 		return -EIO;
110277266186SHannes Reinecke 	}
110377266186SHannes Reinecke 	if (ldev_info->rbld_active) {
110477266186SHannes Reinecke 		return snprintf(buf, 32, "rebuilding block %zu of %zu\n",
110577266186SHannes Reinecke 				(size_t)ldev_info->rbld_lba,
110677266186SHannes Reinecke 				(size_t)ldev_info->cfg_devsize);
110777266186SHannes Reinecke 	} else
110877266186SHannes Reinecke 		return snprintf(buf, 32, "not rebuilding\n");
110977266186SHannes Reinecke }
111077266186SHannes Reinecke 
111177266186SHannes Reinecke static ssize_t rebuild_store(struct device *dev,
111277266186SHannes Reinecke 		struct device_attribute *attr, const char *buf, size_t count)
111377266186SHannes Reinecke {
111477266186SHannes Reinecke 	struct scsi_device *sdev = to_scsi_device(dev);
111577266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(sdev->host);
111677266186SHannes Reinecke 	struct myrs_ldev_info *ldev_info;
111777266186SHannes Reinecke 	struct myrs_cmdblk *cmd_blk;
111877266186SHannes Reinecke 	union myrs_cmd_mbox *mbox;
111977266186SHannes Reinecke 	unsigned short ldev_num;
112077266186SHannes Reinecke 	unsigned char status;
112177266186SHannes Reinecke 	int rebuild, ret;
112277266186SHannes Reinecke 
112377266186SHannes Reinecke 	if (sdev->channel < cs->ctlr_info->physchan_present)
112477266186SHannes Reinecke 		return -EINVAL;
112577266186SHannes Reinecke 
112677266186SHannes Reinecke 	ldev_info = sdev->hostdata;
112777266186SHannes Reinecke 	if (!ldev_info)
112877266186SHannes Reinecke 		return -ENXIO;
112977266186SHannes Reinecke 	ldev_num = ldev_info->ldev_num;
113077266186SHannes Reinecke 
113177266186SHannes Reinecke 	ret = kstrtoint(buf, 0, &rebuild);
113277266186SHannes Reinecke 	if (ret)
113377266186SHannes Reinecke 		return ret;
113477266186SHannes Reinecke 
113577266186SHannes Reinecke 	status = myrs_get_ldev_info(cs, ldev_num, ldev_info);
113677266186SHannes Reinecke 	if (status != MYRS_STATUS_SUCCESS) {
113777266186SHannes Reinecke 		sdev_printk(KERN_INFO, sdev,
113877266186SHannes Reinecke 			    "Failed to get device information, status 0x%02x\n",
113977266186SHannes Reinecke 			    status);
114077266186SHannes Reinecke 		return -EIO;
114177266186SHannes Reinecke 	}
114277266186SHannes Reinecke 
114377266186SHannes Reinecke 	if (rebuild && ldev_info->rbld_active) {
114477266186SHannes Reinecke 		sdev_printk(KERN_INFO, sdev,
114577266186SHannes Reinecke 			    "Rebuild Not Initiated; already in progress\n");
114677266186SHannes Reinecke 		return -EALREADY;
114777266186SHannes Reinecke 	}
114877266186SHannes Reinecke 	if (!rebuild && !ldev_info->rbld_active) {
114977266186SHannes Reinecke 		sdev_printk(KERN_INFO, sdev,
115077266186SHannes Reinecke 			    "Rebuild Not Cancelled; no rebuild in progress\n");
115177266186SHannes Reinecke 		return count;
115277266186SHannes Reinecke 	}
115377266186SHannes Reinecke 
115477266186SHannes Reinecke 	mutex_lock(&cs->dcmd_mutex);
115577266186SHannes Reinecke 	cmd_blk = &cs->dcmd_blk;
115677266186SHannes Reinecke 	myrs_reset_cmd(cmd_blk);
115777266186SHannes Reinecke 	mbox = &cmd_blk->mbox;
115877266186SHannes Reinecke 	mbox->common.opcode = MYRS_CMD_OP_IOCTL;
115977266186SHannes Reinecke 	mbox->common.id = MYRS_DCMD_TAG;
116077266186SHannes Reinecke 	mbox->common.control.dma_ctrl_to_host = true;
116177266186SHannes Reinecke 	mbox->common.control.no_autosense = true;
116277266186SHannes Reinecke 	if (rebuild) {
116377266186SHannes Reinecke 		mbox->ldev_info.ldev.ldev_num = ldev_num;
116477266186SHannes Reinecke 		mbox->ldev_info.ioctl_opcode = MYRS_IOCTL_RBLD_DEVICE_START;
116577266186SHannes Reinecke 	} else {
116677266186SHannes Reinecke 		mbox->ldev_info.ldev.ldev_num = ldev_num;
116777266186SHannes Reinecke 		mbox->ldev_info.ioctl_opcode = MYRS_IOCTL_RBLD_DEVICE_STOP;
116877266186SHannes Reinecke 	}
116977266186SHannes Reinecke 	myrs_exec_cmd(cs, cmd_blk);
117077266186SHannes Reinecke 	status = cmd_blk->status;
117177266186SHannes Reinecke 	mutex_unlock(&cs->dcmd_mutex);
117277266186SHannes Reinecke 	if (status) {
117377266186SHannes Reinecke 		sdev_printk(KERN_INFO, sdev,
117477266186SHannes Reinecke 			    "Rebuild Not %s, status 0x%02x\n",
117577266186SHannes Reinecke 			    rebuild ? "Initiated" : "Cancelled", status);
117677266186SHannes Reinecke 		ret = -EIO;
117777266186SHannes Reinecke 	} else {
117877266186SHannes Reinecke 		sdev_printk(KERN_INFO, sdev, "Rebuild %s\n",
117977266186SHannes Reinecke 			    rebuild ? "Initiated" : "Cancelled");
118077266186SHannes Reinecke 		ret = count;
118177266186SHannes Reinecke 	}
118277266186SHannes Reinecke 
118377266186SHannes Reinecke 	return ret;
118477266186SHannes Reinecke }
118577266186SHannes Reinecke static DEVICE_ATTR_RW(rebuild);
118677266186SHannes Reinecke 
118777266186SHannes Reinecke static ssize_t consistency_check_show(struct device *dev,
118877266186SHannes Reinecke 		struct device_attribute *attr, char *buf)
118977266186SHannes Reinecke {
119077266186SHannes Reinecke 	struct scsi_device *sdev = to_scsi_device(dev);
119177266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(sdev->host);
119277266186SHannes Reinecke 	struct myrs_ldev_info *ldev_info;
119377266186SHannes Reinecke 	unsigned short ldev_num;
119477266186SHannes Reinecke 	unsigned char status;
119577266186SHannes Reinecke 
119677266186SHannes Reinecke 	if (sdev->channel < cs->ctlr_info->physchan_present)
119777266186SHannes Reinecke 		return snprintf(buf, 32, "physical device - not checking\n");
119877266186SHannes Reinecke 
119977266186SHannes Reinecke 	ldev_info = sdev->hostdata;
120077266186SHannes Reinecke 	if (!ldev_info)
120177266186SHannes Reinecke 		return -ENXIO;
120277266186SHannes Reinecke 	ldev_num = ldev_info->ldev_num;
120377266186SHannes Reinecke 	status = myrs_get_ldev_info(cs, ldev_num, ldev_info);
120477266186SHannes Reinecke 	if (ldev_info->cc_active)
120577266186SHannes Reinecke 		return snprintf(buf, 32, "checking block %zu of %zu\n",
120677266186SHannes Reinecke 				(size_t)ldev_info->cc_lba,
120777266186SHannes Reinecke 				(size_t)ldev_info->cfg_devsize);
120877266186SHannes Reinecke 	else
120977266186SHannes Reinecke 		return snprintf(buf, 32, "not checking\n");
121077266186SHannes Reinecke }
121177266186SHannes Reinecke 
121277266186SHannes Reinecke static ssize_t consistency_check_store(struct device *dev,
121377266186SHannes Reinecke 		struct device_attribute *attr, const char *buf, size_t count)
121477266186SHannes Reinecke {
121577266186SHannes Reinecke 	struct scsi_device *sdev = to_scsi_device(dev);
121677266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(sdev->host);
121777266186SHannes Reinecke 	struct myrs_ldev_info *ldev_info;
121877266186SHannes Reinecke 	struct myrs_cmdblk *cmd_blk;
121977266186SHannes Reinecke 	union myrs_cmd_mbox *mbox;
122077266186SHannes Reinecke 	unsigned short ldev_num;
122177266186SHannes Reinecke 	unsigned char status;
122277266186SHannes Reinecke 	int check, ret;
122377266186SHannes Reinecke 
122477266186SHannes Reinecke 	if (sdev->channel < cs->ctlr_info->physchan_present)
122577266186SHannes Reinecke 		return -EINVAL;
122677266186SHannes Reinecke 
122777266186SHannes Reinecke 	ldev_info = sdev->hostdata;
122877266186SHannes Reinecke 	if (!ldev_info)
122977266186SHannes Reinecke 		return -ENXIO;
123077266186SHannes Reinecke 	ldev_num = ldev_info->ldev_num;
123177266186SHannes Reinecke 
123277266186SHannes Reinecke 	ret = kstrtoint(buf, 0, &check);
123377266186SHannes Reinecke 	if (ret)
123477266186SHannes Reinecke 		return ret;
123577266186SHannes Reinecke 
123677266186SHannes Reinecke 	status = myrs_get_ldev_info(cs, ldev_num, ldev_info);
123777266186SHannes Reinecke 	if (status != MYRS_STATUS_SUCCESS) {
123877266186SHannes Reinecke 		sdev_printk(KERN_INFO, sdev,
123977266186SHannes Reinecke 			    "Failed to get device information, status 0x%02x\n",
124077266186SHannes Reinecke 			    status);
124177266186SHannes Reinecke 		return -EIO;
124277266186SHannes Reinecke 	}
124377266186SHannes Reinecke 	if (check && ldev_info->cc_active) {
124477266186SHannes Reinecke 		sdev_printk(KERN_INFO, sdev,
124577266186SHannes Reinecke 			    "Consistency Check Not Initiated; "
124677266186SHannes Reinecke 			    "already in progress\n");
124777266186SHannes Reinecke 		return -EALREADY;
124877266186SHannes Reinecke 	}
124977266186SHannes Reinecke 	if (!check && !ldev_info->cc_active) {
125077266186SHannes Reinecke 		sdev_printk(KERN_INFO, sdev,
125177266186SHannes Reinecke 			    "Consistency Check Not Cancelled; "
125277266186SHannes Reinecke 			    "check not in progress\n");
125377266186SHannes Reinecke 		return count;
125477266186SHannes Reinecke 	}
125577266186SHannes Reinecke 
125677266186SHannes Reinecke 	mutex_lock(&cs->dcmd_mutex);
125777266186SHannes Reinecke 	cmd_blk = &cs->dcmd_blk;
125877266186SHannes Reinecke 	myrs_reset_cmd(cmd_blk);
125977266186SHannes Reinecke 	mbox = &cmd_blk->mbox;
126077266186SHannes Reinecke 	mbox->common.opcode = MYRS_CMD_OP_IOCTL;
126177266186SHannes Reinecke 	mbox->common.id = MYRS_DCMD_TAG;
126277266186SHannes Reinecke 	mbox->common.control.dma_ctrl_to_host = true;
126377266186SHannes Reinecke 	mbox->common.control.no_autosense = true;
126477266186SHannes Reinecke 	if (check) {
126577266186SHannes Reinecke 		mbox->cc.ldev.ldev_num = ldev_num;
126677266186SHannes Reinecke 		mbox->cc.ioctl_opcode = MYRS_IOCTL_CC_START;
126777266186SHannes Reinecke 		mbox->cc.restore_consistency = true;
126877266186SHannes Reinecke 		mbox->cc.initialized_area_only = false;
126977266186SHannes Reinecke 	} else {
127077266186SHannes Reinecke 		mbox->cc.ldev.ldev_num = ldev_num;
127177266186SHannes Reinecke 		mbox->cc.ioctl_opcode = MYRS_IOCTL_CC_STOP;
127277266186SHannes Reinecke 	}
127377266186SHannes Reinecke 	myrs_exec_cmd(cs, cmd_blk);
127477266186SHannes Reinecke 	status = cmd_blk->status;
127577266186SHannes Reinecke 	mutex_unlock(&cs->dcmd_mutex);
127677266186SHannes Reinecke 	if (status != MYRS_STATUS_SUCCESS) {
127777266186SHannes Reinecke 		sdev_printk(KERN_INFO, sdev,
127877266186SHannes Reinecke 			    "Consistency Check Not %s, status 0x%02x\n",
127977266186SHannes Reinecke 			    check ? "Initiated" : "Cancelled", status);
128077266186SHannes Reinecke 		ret = -EIO;
128177266186SHannes Reinecke 	} else {
128277266186SHannes Reinecke 		sdev_printk(KERN_INFO, sdev, "Consistency Check %s\n",
128377266186SHannes Reinecke 			    check ? "Initiated" : "Cancelled");
128477266186SHannes Reinecke 		ret = count;
128577266186SHannes Reinecke 	}
128677266186SHannes Reinecke 
128777266186SHannes Reinecke 	return ret;
128877266186SHannes Reinecke }
128977266186SHannes Reinecke static DEVICE_ATTR_RW(consistency_check);
129077266186SHannes Reinecke 
129177266186SHannes Reinecke static struct device_attribute *myrs_sdev_attrs[] = {
129277266186SHannes Reinecke 	&dev_attr_consistency_check,
129377266186SHannes Reinecke 	&dev_attr_rebuild,
129477266186SHannes Reinecke 	&dev_attr_raid_state,
129577266186SHannes Reinecke 	&dev_attr_raid_level,
129677266186SHannes Reinecke 	NULL,
129777266186SHannes Reinecke };
129877266186SHannes Reinecke 
129977266186SHannes Reinecke static ssize_t serial_show(struct device *dev,
130077266186SHannes Reinecke 		struct device_attribute *attr, char *buf)
130177266186SHannes Reinecke {
130277266186SHannes Reinecke 	struct Scsi_Host *shost = class_to_shost(dev);
130377266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(shost);
130477266186SHannes Reinecke 	char serial[17];
130577266186SHannes Reinecke 
130677266186SHannes Reinecke 	memcpy(serial, cs->ctlr_info->serial_number, 16);
130777266186SHannes Reinecke 	serial[16] = '\0';
130877266186SHannes Reinecke 	return snprintf(buf, 16, "%s\n", serial);
130977266186SHannes Reinecke }
131077266186SHannes Reinecke static DEVICE_ATTR_RO(serial);
131177266186SHannes Reinecke 
131277266186SHannes Reinecke static ssize_t ctlr_num_show(struct device *dev,
131377266186SHannes Reinecke 		struct device_attribute *attr, char *buf)
131477266186SHannes Reinecke {
131577266186SHannes Reinecke 	struct Scsi_Host *shost = class_to_shost(dev);
131677266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(shost);
131777266186SHannes Reinecke 
131877266186SHannes Reinecke 	return snprintf(buf, 20, "%d\n", cs->host->host_no);
131977266186SHannes Reinecke }
132077266186SHannes Reinecke static DEVICE_ATTR_RO(ctlr_num);
132177266186SHannes Reinecke 
132277266186SHannes Reinecke static struct myrs_cpu_type_tbl {
132377266186SHannes Reinecke 	enum myrs_cpu_type type;
132477266186SHannes Reinecke 	char *name;
132577266186SHannes Reinecke } myrs_cpu_type_names[] = {
132677266186SHannes Reinecke 	{ MYRS_CPUTYPE_i960CA, "i960CA" },
132777266186SHannes Reinecke 	{ MYRS_CPUTYPE_i960RD, "i960RD" },
132877266186SHannes Reinecke 	{ MYRS_CPUTYPE_i960RN, "i960RN" },
132977266186SHannes Reinecke 	{ MYRS_CPUTYPE_i960RP, "i960RP" },
133077266186SHannes Reinecke 	{ MYRS_CPUTYPE_NorthBay, "NorthBay" },
133177266186SHannes Reinecke 	{ MYRS_CPUTYPE_StrongArm, "StrongARM" },
133277266186SHannes Reinecke 	{ MYRS_CPUTYPE_i960RM, "i960RM" },
133377266186SHannes Reinecke };
133477266186SHannes Reinecke 
133577266186SHannes Reinecke static ssize_t processor_show(struct device *dev,
133677266186SHannes Reinecke 		struct device_attribute *attr, char *buf)
133777266186SHannes Reinecke {
133877266186SHannes Reinecke 	struct Scsi_Host *shost = class_to_shost(dev);
133977266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(shost);
134077266186SHannes Reinecke 	struct myrs_cpu_type_tbl *tbl;
134177266186SHannes Reinecke 	const char *first_processor = NULL;
134277266186SHannes Reinecke 	const char *second_processor = NULL;
134377266186SHannes Reinecke 	struct myrs_ctlr_info *info = cs->ctlr_info;
134477266186SHannes Reinecke 	ssize_t ret;
134577266186SHannes Reinecke 	int i;
134677266186SHannes Reinecke 
134777266186SHannes Reinecke 	if (info->cpu[0].cpu_count) {
134877266186SHannes Reinecke 		tbl = myrs_cpu_type_names;
134977266186SHannes Reinecke 		for (i = 0; i < ARRAY_SIZE(myrs_cpu_type_names); i++) {
135077266186SHannes Reinecke 			if (tbl[i].type == info->cpu[0].cpu_type) {
135177266186SHannes Reinecke 				first_processor = tbl[i].name;
135277266186SHannes Reinecke 				break;
135377266186SHannes Reinecke 			}
135477266186SHannes Reinecke 		}
135577266186SHannes Reinecke 	}
135677266186SHannes Reinecke 	if (info->cpu[1].cpu_count) {
135777266186SHannes Reinecke 		tbl = myrs_cpu_type_names;
135877266186SHannes Reinecke 		for (i = 0; i < ARRAY_SIZE(myrs_cpu_type_names); i++) {
135977266186SHannes Reinecke 			if (tbl[i].type == info->cpu[1].cpu_type) {
136077266186SHannes Reinecke 				second_processor = tbl[i].name;
136177266186SHannes Reinecke 				break;
136277266186SHannes Reinecke 			}
136377266186SHannes Reinecke 		}
136477266186SHannes Reinecke 	}
136577266186SHannes Reinecke 	if (first_processor && second_processor)
136677266186SHannes Reinecke 		ret = snprintf(buf, 64, "1: %s (%s, %d cpus)\n"
136777266186SHannes Reinecke 			       "2: %s (%s, %d cpus)\n",
136877266186SHannes Reinecke 			       info->cpu[0].cpu_name,
136977266186SHannes Reinecke 			       first_processor, info->cpu[0].cpu_count,
137077266186SHannes Reinecke 			       info->cpu[1].cpu_name,
137177266186SHannes Reinecke 			       second_processor, info->cpu[1].cpu_count);
1372a0db8a75SDan Carpenter 	else if (first_processor && !second_processor)
137377266186SHannes Reinecke 		ret = snprintf(buf, 64, "1: %s (%s, %d cpus)\n2: absent\n",
137477266186SHannes Reinecke 			       info->cpu[0].cpu_name,
137577266186SHannes Reinecke 			       first_processor, info->cpu[0].cpu_count);
1376a0db8a75SDan Carpenter 	else if (!first_processor && second_processor)
137777266186SHannes Reinecke 		ret = snprintf(buf, 64, "1: absent\n2: %s (%s, %d cpus)\n",
137877266186SHannes Reinecke 			       info->cpu[1].cpu_name,
137977266186SHannes Reinecke 			       second_processor, info->cpu[1].cpu_count);
138077266186SHannes Reinecke 	else
138177266186SHannes Reinecke 		ret = snprintf(buf, 64, "1: absent\n2: absent\n");
138277266186SHannes Reinecke 
138377266186SHannes Reinecke 	return ret;
138477266186SHannes Reinecke }
138577266186SHannes Reinecke static DEVICE_ATTR_RO(processor);
138677266186SHannes Reinecke 
138777266186SHannes Reinecke static ssize_t model_show(struct device *dev,
138877266186SHannes Reinecke 		struct device_attribute *attr, char *buf)
138977266186SHannes Reinecke {
139077266186SHannes Reinecke 	struct Scsi_Host *shost = class_to_shost(dev);
139177266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(shost);
139277266186SHannes Reinecke 
139377266186SHannes Reinecke 	return snprintf(buf, 28, "%s\n", cs->model_name);
139477266186SHannes Reinecke }
139577266186SHannes Reinecke static DEVICE_ATTR_RO(model);
139677266186SHannes Reinecke 
139777266186SHannes Reinecke static ssize_t ctlr_type_show(struct device *dev,
139877266186SHannes Reinecke 		struct device_attribute *attr, char *buf)
139977266186SHannes Reinecke {
140077266186SHannes Reinecke 	struct Scsi_Host *shost = class_to_shost(dev);
140177266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(shost);
140277266186SHannes Reinecke 
140377266186SHannes Reinecke 	return snprintf(buf, 4, "%d\n", cs->ctlr_info->ctlr_type);
140477266186SHannes Reinecke }
140577266186SHannes Reinecke static DEVICE_ATTR_RO(ctlr_type);
140677266186SHannes Reinecke 
140777266186SHannes Reinecke static ssize_t cache_size_show(struct device *dev,
140877266186SHannes Reinecke 		struct device_attribute *attr, char *buf)
140977266186SHannes Reinecke {
141077266186SHannes Reinecke 	struct Scsi_Host *shost = class_to_shost(dev);
141177266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(shost);
141277266186SHannes Reinecke 
141377266186SHannes Reinecke 	return snprintf(buf, 8, "%d MB\n", cs->ctlr_info->cache_size_mb);
141477266186SHannes Reinecke }
141577266186SHannes Reinecke static DEVICE_ATTR_RO(cache_size);
141677266186SHannes Reinecke 
141777266186SHannes Reinecke static ssize_t firmware_show(struct device *dev,
141877266186SHannes Reinecke 		struct device_attribute *attr, char *buf)
141977266186SHannes Reinecke {
142077266186SHannes Reinecke 	struct Scsi_Host *shost = class_to_shost(dev);
142177266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(shost);
142277266186SHannes Reinecke 
142377266186SHannes Reinecke 	return snprintf(buf, 16, "%d.%02d-%02d\n",
142477266186SHannes Reinecke 			cs->ctlr_info->fw_major_version,
142577266186SHannes Reinecke 			cs->ctlr_info->fw_minor_version,
142677266186SHannes Reinecke 			cs->ctlr_info->fw_turn_number);
142777266186SHannes Reinecke }
142877266186SHannes Reinecke static DEVICE_ATTR_RO(firmware);
142977266186SHannes Reinecke 
143077266186SHannes Reinecke static ssize_t discovery_store(struct device *dev,
143177266186SHannes Reinecke 		struct device_attribute *attr, const char *buf, size_t count)
143277266186SHannes Reinecke {
143377266186SHannes Reinecke 	struct Scsi_Host *shost = class_to_shost(dev);
143477266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(shost);
143577266186SHannes Reinecke 	struct myrs_cmdblk *cmd_blk;
143677266186SHannes Reinecke 	union myrs_cmd_mbox *mbox;
143777266186SHannes Reinecke 	unsigned char status;
143877266186SHannes Reinecke 
143977266186SHannes Reinecke 	mutex_lock(&cs->dcmd_mutex);
144077266186SHannes Reinecke 	cmd_blk = &cs->dcmd_blk;
144177266186SHannes Reinecke 	myrs_reset_cmd(cmd_blk);
144277266186SHannes Reinecke 	mbox = &cmd_blk->mbox;
144377266186SHannes Reinecke 	mbox->common.opcode = MYRS_CMD_OP_IOCTL;
144477266186SHannes Reinecke 	mbox->common.id = MYRS_DCMD_TAG;
144577266186SHannes Reinecke 	mbox->common.control.dma_ctrl_to_host = true;
144677266186SHannes Reinecke 	mbox->common.control.no_autosense = true;
144777266186SHannes Reinecke 	mbox->common.ioctl_opcode = MYRS_IOCTL_START_DISCOVERY;
144877266186SHannes Reinecke 	myrs_exec_cmd(cs, cmd_blk);
144977266186SHannes Reinecke 	status = cmd_blk->status;
145077266186SHannes Reinecke 	mutex_unlock(&cs->dcmd_mutex);
145177266186SHannes Reinecke 	if (status != MYRS_STATUS_SUCCESS) {
145277266186SHannes Reinecke 		shost_printk(KERN_INFO, shost,
145377266186SHannes Reinecke 			     "Discovery Not Initiated, status %02X\n",
145477266186SHannes Reinecke 			     status);
145577266186SHannes Reinecke 		return -EINVAL;
145677266186SHannes Reinecke 	}
145777266186SHannes Reinecke 	shost_printk(KERN_INFO, shost, "Discovery Initiated\n");
145877266186SHannes Reinecke 	cs->next_evseq = 0;
145977266186SHannes Reinecke 	cs->needs_update = true;
146077266186SHannes Reinecke 	queue_delayed_work(cs->work_q, &cs->monitor_work, 1);
146177266186SHannes Reinecke 	flush_delayed_work(&cs->monitor_work);
146277266186SHannes Reinecke 	shost_printk(KERN_INFO, shost, "Discovery Completed\n");
146377266186SHannes Reinecke 
146477266186SHannes Reinecke 	return count;
146577266186SHannes Reinecke }
146677266186SHannes Reinecke static DEVICE_ATTR_WO(discovery);
146777266186SHannes Reinecke 
146877266186SHannes Reinecke static ssize_t flush_cache_store(struct device *dev,
146977266186SHannes Reinecke 		struct device_attribute *attr, const char *buf, size_t count)
147077266186SHannes Reinecke {
147177266186SHannes Reinecke 	struct Scsi_Host *shost = class_to_shost(dev);
147277266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(shost);
147377266186SHannes Reinecke 	unsigned char status;
147477266186SHannes Reinecke 
147577266186SHannes Reinecke 	status = myrs_dev_op(cs, MYRS_IOCTL_FLUSH_DEVICE_DATA,
147677266186SHannes Reinecke 			     MYRS_RAID_CONTROLLER);
147777266186SHannes Reinecke 	if (status == MYRS_STATUS_SUCCESS) {
147877266186SHannes Reinecke 		shost_printk(KERN_INFO, shost, "Cache Flush Completed\n");
147977266186SHannes Reinecke 		return count;
148077266186SHannes Reinecke 	}
148177266186SHannes Reinecke 	shost_printk(KERN_INFO, shost,
148277266186SHannes Reinecke 		     "Cache Flush failed, status 0x%02x\n", status);
148377266186SHannes Reinecke 	return -EIO;
148477266186SHannes Reinecke }
148577266186SHannes Reinecke static DEVICE_ATTR_WO(flush_cache);
148677266186SHannes Reinecke 
148777266186SHannes Reinecke static ssize_t disable_enclosure_messages_show(struct device *dev,
148877266186SHannes Reinecke 		struct device_attribute *attr, char *buf)
148977266186SHannes Reinecke {
149077266186SHannes Reinecke 	struct Scsi_Host *shost = class_to_shost(dev);
149177266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(shost);
149277266186SHannes Reinecke 
149377266186SHannes Reinecke 	return snprintf(buf, 3, "%d\n", cs->disable_enc_msg);
149477266186SHannes Reinecke }
149577266186SHannes Reinecke 
149677266186SHannes Reinecke static ssize_t disable_enclosure_messages_store(struct device *dev,
149777266186SHannes Reinecke 		struct device_attribute *attr, const char *buf, size_t count)
149877266186SHannes Reinecke {
149977266186SHannes Reinecke 	struct scsi_device *sdev = to_scsi_device(dev);
150077266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(sdev->host);
150177266186SHannes Reinecke 	int value, ret;
150277266186SHannes Reinecke 
150377266186SHannes Reinecke 	ret = kstrtoint(buf, 0, &value);
150477266186SHannes Reinecke 	if (ret)
150577266186SHannes Reinecke 		return ret;
150677266186SHannes Reinecke 
150777266186SHannes Reinecke 	if (value > 2)
150877266186SHannes Reinecke 		return -EINVAL;
150977266186SHannes Reinecke 
151077266186SHannes Reinecke 	cs->disable_enc_msg = value;
151177266186SHannes Reinecke 	return count;
151277266186SHannes Reinecke }
151377266186SHannes Reinecke static DEVICE_ATTR_RW(disable_enclosure_messages);
151477266186SHannes Reinecke 
151577266186SHannes Reinecke static struct device_attribute *myrs_shost_attrs[] = {
151677266186SHannes Reinecke 	&dev_attr_serial,
151777266186SHannes Reinecke 	&dev_attr_ctlr_num,
151877266186SHannes Reinecke 	&dev_attr_processor,
151977266186SHannes Reinecke 	&dev_attr_model,
152077266186SHannes Reinecke 	&dev_attr_ctlr_type,
152177266186SHannes Reinecke 	&dev_attr_cache_size,
152277266186SHannes Reinecke 	&dev_attr_firmware,
152377266186SHannes Reinecke 	&dev_attr_discovery,
152477266186SHannes Reinecke 	&dev_attr_flush_cache,
152577266186SHannes Reinecke 	&dev_attr_disable_enclosure_messages,
152677266186SHannes Reinecke 	NULL,
152777266186SHannes Reinecke };
152877266186SHannes Reinecke 
152977266186SHannes Reinecke /*
153077266186SHannes Reinecke  * SCSI midlayer interface
153177266186SHannes Reinecke  */
153277266186SHannes Reinecke int myrs_host_reset(struct scsi_cmnd *scmd)
153377266186SHannes Reinecke {
153477266186SHannes Reinecke 	struct Scsi_Host *shost = scmd->device->host;
153577266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(shost);
153677266186SHannes Reinecke 
153777266186SHannes Reinecke 	cs->reset(cs->io_base);
153877266186SHannes Reinecke 	return SUCCESS;
153977266186SHannes Reinecke }
154077266186SHannes Reinecke 
154177266186SHannes Reinecke static void myrs_mode_sense(struct myrs_hba *cs, struct scsi_cmnd *scmd,
154277266186SHannes Reinecke 		struct myrs_ldev_info *ldev_info)
154377266186SHannes Reinecke {
154477266186SHannes Reinecke 	unsigned char modes[32], *mode_pg;
154577266186SHannes Reinecke 	bool dbd;
154677266186SHannes Reinecke 	size_t mode_len;
154777266186SHannes Reinecke 
154877266186SHannes Reinecke 	dbd = (scmd->cmnd[1] & 0x08) == 0x08;
154977266186SHannes Reinecke 	if (dbd) {
155077266186SHannes Reinecke 		mode_len = 24;
155177266186SHannes Reinecke 		mode_pg = &modes[4];
155277266186SHannes Reinecke 	} else {
155377266186SHannes Reinecke 		mode_len = 32;
155477266186SHannes Reinecke 		mode_pg = &modes[12];
155577266186SHannes Reinecke 	}
155677266186SHannes Reinecke 	memset(modes, 0, sizeof(modes));
155777266186SHannes Reinecke 	modes[0] = mode_len - 1;
155877266186SHannes Reinecke 	modes[2] = 0x10; /* Enable FUA */
155977266186SHannes Reinecke 	if (ldev_info->ldev_control.wce == MYRS_LOGICALDEVICE_RO)
156077266186SHannes Reinecke 		modes[2] |= 0x80;
156177266186SHannes Reinecke 	if (!dbd) {
156277266186SHannes Reinecke 		unsigned char *block_desc = &modes[4];
156377266186SHannes Reinecke 
156477266186SHannes Reinecke 		modes[3] = 8;
156577266186SHannes Reinecke 		put_unaligned_be32(ldev_info->cfg_devsize, &block_desc[0]);
156677266186SHannes Reinecke 		put_unaligned_be32(ldev_info->devsize_bytes, &block_desc[5]);
156777266186SHannes Reinecke 	}
156877266186SHannes Reinecke 	mode_pg[0] = 0x08;
156977266186SHannes Reinecke 	mode_pg[1] = 0x12;
157077266186SHannes Reinecke 	if (ldev_info->ldev_control.rce == MYRS_READCACHE_DISABLED)
157177266186SHannes Reinecke 		mode_pg[2] |= 0x01;
157277266186SHannes Reinecke 	if (ldev_info->ldev_control.wce == MYRS_WRITECACHE_ENABLED ||
157377266186SHannes Reinecke 	    ldev_info->ldev_control.wce == MYRS_INTELLIGENT_WRITECACHE_ENABLED)
157477266186SHannes Reinecke 		mode_pg[2] |= 0x04;
157577266186SHannes Reinecke 	if (ldev_info->cacheline_size) {
157677266186SHannes Reinecke 		mode_pg[2] |= 0x08;
157777266186SHannes Reinecke 		put_unaligned_be16(1 << ldev_info->cacheline_size,
157877266186SHannes Reinecke 				   &mode_pg[14]);
157977266186SHannes Reinecke 	}
158077266186SHannes Reinecke 
158177266186SHannes Reinecke 	scsi_sg_copy_from_buffer(scmd, modes, mode_len);
158277266186SHannes Reinecke }
158377266186SHannes Reinecke 
158477266186SHannes Reinecke static int myrs_queuecommand(struct Scsi_Host *shost,
158577266186SHannes Reinecke 		struct scsi_cmnd *scmd)
158677266186SHannes Reinecke {
158777266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(shost);
158877266186SHannes Reinecke 	struct myrs_cmdblk *cmd_blk = scsi_cmd_priv(scmd);
158977266186SHannes Reinecke 	union myrs_cmd_mbox *mbox = &cmd_blk->mbox;
159077266186SHannes Reinecke 	struct scsi_device *sdev = scmd->device;
159177266186SHannes Reinecke 	union myrs_sgl *hw_sge;
159277266186SHannes Reinecke 	dma_addr_t sense_addr;
159377266186SHannes Reinecke 	struct scatterlist *sgl;
159477266186SHannes Reinecke 	unsigned long flags, timeout;
159577266186SHannes Reinecke 	int nsge;
159677266186SHannes Reinecke 
159777266186SHannes Reinecke 	if (!scmd->device->hostdata) {
159877266186SHannes Reinecke 		scmd->result = (DID_NO_CONNECT << 16);
159977266186SHannes Reinecke 		scmd->scsi_done(scmd);
160077266186SHannes Reinecke 		return 0;
160177266186SHannes Reinecke 	}
160277266186SHannes Reinecke 
160377266186SHannes Reinecke 	switch (scmd->cmnd[0]) {
160477266186SHannes Reinecke 	case REPORT_LUNS:
160577266186SHannes Reinecke 		scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST,
160677266186SHannes Reinecke 					0x20, 0x0);
160777266186SHannes Reinecke 		scmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
160877266186SHannes Reinecke 		scmd->scsi_done(scmd);
160977266186SHannes Reinecke 		return 0;
161077266186SHannes Reinecke 	case MODE_SENSE:
161177266186SHannes Reinecke 		if (scmd->device->channel >= cs->ctlr_info->physchan_present) {
161277266186SHannes Reinecke 			struct myrs_ldev_info *ldev_info = sdev->hostdata;
161377266186SHannes Reinecke 
161477266186SHannes Reinecke 			if ((scmd->cmnd[2] & 0x3F) != 0x3F &&
161577266186SHannes Reinecke 			    (scmd->cmnd[2] & 0x3F) != 0x08) {
161677266186SHannes Reinecke 				/* Illegal request, invalid field in CDB */
161777266186SHannes Reinecke 				scsi_build_sense_buffer(0, scmd->sense_buffer,
161877266186SHannes Reinecke 					ILLEGAL_REQUEST, 0x24, 0);
161977266186SHannes Reinecke 				scmd->result = (DRIVER_SENSE << 24) |
162077266186SHannes Reinecke 					SAM_STAT_CHECK_CONDITION;
162177266186SHannes Reinecke 			} else {
162277266186SHannes Reinecke 				myrs_mode_sense(cs, scmd, ldev_info);
162377266186SHannes Reinecke 				scmd->result = (DID_OK << 16);
162477266186SHannes Reinecke 			}
162577266186SHannes Reinecke 			scmd->scsi_done(scmd);
162677266186SHannes Reinecke 			return 0;
162777266186SHannes Reinecke 		}
162877266186SHannes Reinecke 		break;
162977266186SHannes Reinecke 	}
163077266186SHannes Reinecke 
163177266186SHannes Reinecke 	myrs_reset_cmd(cmd_blk);
163277266186SHannes Reinecke 	cmd_blk->sense = dma_pool_alloc(cs->sense_pool, GFP_ATOMIC,
163377266186SHannes Reinecke 					&sense_addr);
163477266186SHannes Reinecke 	if (!cmd_blk->sense)
163577266186SHannes Reinecke 		return SCSI_MLQUEUE_HOST_BUSY;
163677266186SHannes Reinecke 	cmd_blk->sense_addr = sense_addr;
163777266186SHannes Reinecke 
163877266186SHannes Reinecke 	timeout = scmd->request->timeout;
163977266186SHannes Reinecke 	if (scmd->cmd_len <= 10) {
164077266186SHannes Reinecke 		if (scmd->device->channel >= cs->ctlr_info->physchan_present) {
164177266186SHannes Reinecke 			struct myrs_ldev_info *ldev_info = sdev->hostdata;
164277266186SHannes Reinecke 
164377266186SHannes Reinecke 			mbox->SCSI_10.opcode = MYRS_CMD_OP_SCSI_10;
164477266186SHannes Reinecke 			mbox->SCSI_10.pdev.lun = ldev_info->lun;
164577266186SHannes Reinecke 			mbox->SCSI_10.pdev.target = ldev_info->target;
164677266186SHannes Reinecke 			mbox->SCSI_10.pdev.channel = ldev_info->channel;
164777266186SHannes Reinecke 			mbox->SCSI_10.pdev.ctlr = 0;
164877266186SHannes Reinecke 		} else {
164977266186SHannes Reinecke 			mbox->SCSI_10.opcode = MYRS_CMD_OP_SCSI_10_PASSTHRU;
165077266186SHannes Reinecke 			mbox->SCSI_10.pdev.lun = sdev->lun;
165177266186SHannes Reinecke 			mbox->SCSI_10.pdev.target = sdev->id;
165277266186SHannes Reinecke 			mbox->SCSI_10.pdev.channel = sdev->channel;
165377266186SHannes Reinecke 		}
165477266186SHannes Reinecke 		mbox->SCSI_10.id = scmd->request->tag + 3;
165577266186SHannes Reinecke 		mbox->SCSI_10.control.dma_ctrl_to_host =
165677266186SHannes Reinecke 			(scmd->sc_data_direction == DMA_FROM_DEVICE);
165777266186SHannes Reinecke 		if (scmd->request->cmd_flags & REQ_FUA)
165877266186SHannes Reinecke 			mbox->SCSI_10.control.fua = true;
165977266186SHannes Reinecke 		mbox->SCSI_10.dma_size = scsi_bufflen(scmd);
166077266186SHannes Reinecke 		mbox->SCSI_10.sense_addr = cmd_blk->sense_addr;
166177266186SHannes Reinecke 		mbox->SCSI_10.sense_len = MYRS_SENSE_SIZE;
166277266186SHannes Reinecke 		mbox->SCSI_10.cdb_len = scmd->cmd_len;
166377266186SHannes Reinecke 		if (timeout > 60) {
166477266186SHannes Reinecke 			mbox->SCSI_10.tmo.tmo_scale = MYRS_TMO_SCALE_MINUTES;
166577266186SHannes Reinecke 			mbox->SCSI_10.tmo.tmo_val = timeout / 60;
166677266186SHannes Reinecke 		} else {
166777266186SHannes Reinecke 			mbox->SCSI_10.tmo.tmo_scale = MYRS_TMO_SCALE_SECONDS;
166877266186SHannes Reinecke 			mbox->SCSI_10.tmo.tmo_val = timeout;
166977266186SHannes Reinecke 		}
167077266186SHannes Reinecke 		memcpy(&mbox->SCSI_10.cdb, scmd->cmnd, scmd->cmd_len);
167177266186SHannes Reinecke 		hw_sge = &mbox->SCSI_10.dma_addr;
167277266186SHannes Reinecke 		cmd_blk->dcdb = NULL;
167377266186SHannes Reinecke 	} else {
167477266186SHannes Reinecke 		dma_addr_t dcdb_dma;
167577266186SHannes Reinecke 
167677266186SHannes Reinecke 		cmd_blk->dcdb = dma_pool_alloc(cs->dcdb_pool, GFP_ATOMIC,
167777266186SHannes Reinecke 					       &dcdb_dma);
167877266186SHannes Reinecke 		if (!cmd_blk->dcdb) {
167977266186SHannes Reinecke 			dma_pool_free(cs->sense_pool, cmd_blk->sense,
168077266186SHannes Reinecke 				      cmd_blk->sense_addr);
168177266186SHannes Reinecke 			cmd_blk->sense = NULL;
168277266186SHannes Reinecke 			cmd_blk->sense_addr = 0;
168377266186SHannes Reinecke 			return SCSI_MLQUEUE_HOST_BUSY;
168477266186SHannes Reinecke 		}
168577266186SHannes Reinecke 		cmd_blk->dcdb_dma = dcdb_dma;
168677266186SHannes Reinecke 		if (scmd->device->channel >= cs->ctlr_info->physchan_present) {
168777266186SHannes Reinecke 			struct myrs_ldev_info *ldev_info = sdev->hostdata;
168877266186SHannes Reinecke 
168977266186SHannes Reinecke 			mbox->SCSI_255.opcode = MYRS_CMD_OP_SCSI_256;
169077266186SHannes Reinecke 			mbox->SCSI_255.pdev.lun = ldev_info->lun;
169177266186SHannes Reinecke 			mbox->SCSI_255.pdev.target = ldev_info->target;
169277266186SHannes Reinecke 			mbox->SCSI_255.pdev.channel = ldev_info->channel;
169377266186SHannes Reinecke 			mbox->SCSI_255.pdev.ctlr = 0;
169477266186SHannes Reinecke 		} else {
169577266186SHannes Reinecke 			mbox->SCSI_255.opcode = MYRS_CMD_OP_SCSI_255_PASSTHRU;
169677266186SHannes Reinecke 			mbox->SCSI_255.pdev.lun = sdev->lun;
169777266186SHannes Reinecke 			mbox->SCSI_255.pdev.target = sdev->id;
169877266186SHannes Reinecke 			mbox->SCSI_255.pdev.channel = sdev->channel;
169977266186SHannes Reinecke 		}
170077266186SHannes Reinecke 		mbox->SCSI_255.id = scmd->request->tag + 3;
170177266186SHannes Reinecke 		mbox->SCSI_255.control.dma_ctrl_to_host =
170277266186SHannes Reinecke 			(scmd->sc_data_direction == DMA_FROM_DEVICE);
170377266186SHannes Reinecke 		if (scmd->request->cmd_flags & REQ_FUA)
170477266186SHannes Reinecke 			mbox->SCSI_255.control.fua = true;
170577266186SHannes Reinecke 		mbox->SCSI_255.dma_size = scsi_bufflen(scmd);
170677266186SHannes Reinecke 		mbox->SCSI_255.sense_addr = cmd_blk->sense_addr;
170777266186SHannes Reinecke 		mbox->SCSI_255.sense_len = MYRS_SENSE_SIZE;
170877266186SHannes Reinecke 		mbox->SCSI_255.cdb_len = scmd->cmd_len;
170977266186SHannes Reinecke 		mbox->SCSI_255.cdb_addr = cmd_blk->dcdb_dma;
171077266186SHannes Reinecke 		if (timeout > 60) {
171177266186SHannes Reinecke 			mbox->SCSI_255.tmo.tmo_scale = MYRS_TMO_SCALE_MINUTES;
171277266186SHannes Reinecke 			mbox->SCSI_255.tmo.tmo_val = timeout / 60;
171377266186SHannes Reinecke 		} else {
171477266186SHannes Reinecke 			mbox->SCSI_255.tmo.tmo_scale = MYRS_TMO_SCALE_SECONDS;
171577266186SHannes Reinecke 			mbox->SCSI_255.tmo.tmo_val = timeout;
171677266186SHannes Reinecke 		}
171777266186SHannes Reinecke 		memcpy(cmd_blk->dcdb, scmd->cmnd, scmd->cmd_len);
171877266186SHannes Reinecke 		hw_sge = &mbox->SCSI_255.dma_addr;
171977266186SHannes Reinecke 	}
172077266186SHannes Reinecke 	if (scmd->sc_data_direction == DMA_NONE)
172177266186SHannes Reinecke 		goto submit;
172277266186SHannes Reinecke 	nsge = scsi_dma_map(scmd);
172377266186SHannes Reinecke 	if (nsge == 1) {
172477266186SHannes Reinecke 		sgl = scsi_sglist(scmd);
172577266186SHannes Reinecke 		hw_sge->sge[0].sge_addr = (u64)sg_dma_address(sgl);
172677266186SHannes Reinecke 		hw_sge->sge[0].sge_count = (u64)sg_dma_len(sgl);
172777266186SHannes Reinecke 	} else {
172877266186SHannes Reinecke 		struct myrs_sge *hw_sgl;
172977266186SHannes Reinecke 		dma_addr_t hw_sgl_addr;
173077266186SHannes Reinecke 		int i;
173177266186SHannes Reinecke 
173277266186SHannes Reinecke 		if (nsge > 2) {
173377266186SHannes Reinecke 			hw_sgl = dma_pool_alloc(cs->sg_pool, GFP_ATOMIC,
173477266186SHannes Reinecke 						&hw_sgl_addr);
173577266186SHannes Reinecke 			if (WARN_ON(!hw_sgl)) {
173677266186SHannes Reinecke 				if (cmd_blk->dcdb) {
173777266186SHannes Reinecke 					dma_pool_free(cs->dcdb_pool,
173877266186SHannes Reinecke 						      cmd_blk->dcdb,
173977266186SHannes Reinecke 						      cmd_blk->dcdb_dma);
174077266186SHannes Reinecke 					cmd_blk->dcdb = NULL;
174177266186SHannes Reinecke 					cmd_blk->dcdb_dma = 0;
174277266186SHannes Reinecke 				}
174377266186SHannes Reinecke 				dma_pool_free(cs->sense_pool,
174477266186SHannes Reinecke 					      cmd_blk->sense,
174577266186SHannes Reinecke 					      cmd_blk->sense_addr);
174677266186SHannes Reinecke 				cmd_blk->sense = NULL;
174777266186SHannes Reinecke 				cmd_blk->sense_addr = 0;
174877266186SHannes Reinecke 				return SCSI_MLQUEUE_HOST_BUSY;
174977266186SHannes Reinecke 			}
175077266186SHannes Reinecke 			cmd_blk->sgl = hw_sgl;
175177266186SHannes Reinecke 			cmd_blk->sgl_addr = hw_sgl_addr;
175277266186SHannes Reinecke 			if (scmd->cmd_len <= 10)
175377266186SHannes Reinecke 				mbox->SCSI_10.control.add_sge_mem = true;
175477266186SHannes Reinecke 			else
175577266186SHannes Reinecke 				mbox->SCSI_255.control.add_sge_mem = true;
175677266186SHannes Reinecke 			hw_sge->ext.sge0_len = nsge;
175777266186SHannes Reinecke 			hw_sge->ext.sge0_addr = cmd_blk->sgl_addr;
175877266186SHannes Reinecke 		} else
175977266186SHannes Reinecke 			hw_sgl = hw_sge->sge;
176077266186SHannes Reinecke 
176177266186SHannes Reinecke 		scsi_for_each_sg(scmd, sgl, nsge, i) {
176277266186SHannes Reinecke 			if (WARN_ON(!hw_sgl)) {
176377266186SHannes Reinecke 				scsi_dma_unmap(scmd);
176477266186SHannes Reinecke 				scmd->result = (DID_ERROR << 16);
176577266186SHannes Reinecke 				scmd->scsi_done(scmd);
176677266186SHannes Reinecke 				return 0;
176777266186SHannes Reinecke 			}
176877266186SHannes Reinecke 			hw_sgl->sge_addr = (u64)sg_dma_address(sgl);
176977266186SHannes Reinecke 			hw_sgl->sge_count = (u64)sg_dma_len(sgl);
177077266186SHannes Reinecke 			hw_sgl++;
177177266186SHannes Reinecke 		}
177277266186SHannes Reinecke 	}
177377266186SHannes Reinecke submit:
177477266186SHannes Reinecke 	spin_lock_irqsave(&cs->queue_lock, flags);
177577266186SHannes Reinecke 	myrs_qcmd(cs, cmd_blk);
177677266186SHannes Reinecke 	spin_unlock_irqrestore(&cs->queue_lock, flags);
177777266186SHannes Reinecke 
177877266186SHannes Reinecke 	return 0;
177977266186SHannes Reinecke }
178077266186SHannes Reinecke 
178177266186SHannes Reinecke static unsigned short myrs_translate_ldev(struct myrs_hba *cs,
178277266186SHannes Reinecke 		struct scsi_device *sdev)
178377266186SHannes Reinecke {
178477266186SHannes Reinecke 	unsigned short ldev_num;
178577266186SHannes Reinecke 	unsigned int chan_offset =
178677266186SHannes Reinecke 		sdev->channel - cs->ctlr_info->physchan_present;
178777266186SHannes Reinecke 
178877266186SHannes Reinecke 	ldev_num = sdev->id + chan_offset * sdev->host->max_id;
178977266186SHannes Reinecke 
179077266186SHannes Reinecke 	return ldev_num;
179177266186SHannes Reinecke }
179277266186SHannes Reinecke 
179377266186SHannes Reinecke static int myrs_slave_alloc(struct scsi_device *sdev)
179477266186SHannes Reinecke {
179577266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(sdev->host);
179677266186SHannes Reinecke 	unsigned char status;
179777266186SHannes Reinecke 
179877266186SHannes Reinecke 	if (sdev->channel > sdev->host->max_channel)
179977266186SHannes Reinecke 		return 0;
180077266186SHannes Reinecke 
180177266186SHannes Reinecke 	if (sdev->channel >= cs->ctlr_info->physchan_present) {
180277266186SHannes Reinecke 		struct myrs_ldev_info *ldev_info;
180377266186SHannes Reinecke 		unsigned short ldev_num;
180477266186SHannes Reinecke 
180577266186SHannes Reinecke 		if (sdev->lun > 0)
180677266186SHannes Reinecke 			return -ENXIO;
180777266186SHannes Reinecke 
180877266186SHannes Reinecke 		ldev_num = myrs_translate_ldev(cs, sdev);
180977266186SHannes Reinecke 
181077266186SHannes Reinecke 		ldev_info = kzalloc(sizeof(*ldev_info), GFP_KERNEL|GFP_DMA);
181177266186SHannes Reinecke 		if (!ldev_info)
181277266186SHannes Reinecke 			return -ENOMEM;
181377266186SHannes Reinecke 
181477266186SHannes Reinecke 		status = myrs_get_ldev_info(cs, ldev_num, ldev_info);
181577266186SHannes Reinecke 		if (status != MYRS_STATUS_SUCCESS) {
181677266186SHannes Reinecke 			sdev->hostdata = NULL;
181777266186SHannes Reinecke 			kfree(ldev_info);
181877266186SHannes Reinecke 		} else {
181977266186SHannes Reinecke 			enum raid_level level;
182077266186SHannes Reinecke 
182177266186SHannes Reinecke 			dev_dbg(&sdev->sdev_gendev,
182277266186SHannes Reinecke 				"Logical device mapping %d:%d:%d -> %d\n",
182377266186SHannes Reinecke 				ldev_info->channel, ldev_info->target,
182477266186SHannes Reinecke 				ldev_info->lun, ldev_info->ldev_num);
182577266186SHannes Reinecke 
182677266186SHannes Reinecke 			sdev->hostdata = ldev_info;
182777266186SHannes Reinecke 			switch (ldev_info->raid_level) {
182877266186SHannes Reinecke 			case MYRS_RAID_LEVEL0:
182977266186SHannes Reinecke 				level = RAID_LEVEL_LINEAR;
183077266186SHannes Reinecke 				break;
183177266186SHannes Reinecke 			case MYRS_RAID_LEVEL1:
183277266186SHannes Reinecke 				level = RAID_LEVEL_1;
183377266186SHannes Reinecke 				break;
183477266186SHannes Reinecke 			case MYRS_RAID_LEVEL3:
183577266186SHannes Reinecke 			case MYRS_RAID_LEVEL3F:
183677266186SHannes Reinecke 			case MYRS_RAID_LEVEL3L:
183777266186SHannes Reinecke 				level = RAID_LEVEL_3;
183877266186SHannes Reinecke 				break;
183977266186SHannes Reinecke 			case MYRS_RAID_LEVEL5:
184077266186SHannes Reinecke 			case MYRS_RAID_LEVEL5L:
184177266186SHannes Reinecke 				level = RAID_LEVEL_5;
184277266186SHannes Reinecke 				break;
184377266186SHannes Reinecke 			case MYRS_RAID_LEVEL6:
184477266186SHannes Reinecke 				level = RAID_LEVEL_6;
184577266186SHannes Reinecke 				break;
184677266186SHannes Reinecke 			case MYRS_RAID_LEVELE:
184777266186SHannes Reinecke 			case MYRS_RAID_NEWSPAN:
184877266186SHannes Reinecke 			case MYRS_RAID_SPAN:
184977266186SHannes Reinecke 				level = RAID_LEVEL_LINEAR;
185077266186SHannes Reinecke 				break;
185177266186SHannes Reinecke 			case MYRS_RAID_JBOD:
185277266186SHannes Reinecke 				level = RAID_LEVEL_JBOD;
185377266186SHannes Reinecke 				break;
185477266186SHannes Reinecke 			default:
185577266186SHannes Reinecke 				level = RAID_LEVEL_UNKNOWN;
185677266186SHannes Reinecke 				break;
185777266186SHannes Reinecke 			}
185877266186SHannes Reinecke 			raid_set_level(myrs_raid_template,
185977266186SHannes Reinecke 				       &sdev->sdev_gendev, level);
186077266186SHannes Reinecke 			if (ldev_info->dev_state != MYRS_DEVICE_ONLINE) {
186177266186SHannes Reinecke 				const char *name;
186277266186SHannes Reinecke 
186377266186SHannes Reinecke 				name = myrs_devstate_name(ldev_info->dev_state);
186477266186SHannes Reinecke 				sdev_printk(KERN_DEBUG, sdev,
186577266186SHannes Reinecke 					    "logical device in state %s\n",
186677266186SHannes Reinecke 					    name ? name : "Invalid");
186777266186SHannes Reinecke 			}
186877266186SHannes Reinecke 		}
186977266186SHannes Reinecke 	} else {
187077266186SHannes Reinecke 		struct myrs_pdev_info *pdev_info;
187177266186SHannes Reinecke 
187277266186SHannes Reinecke 		pdev_info = kzalloc(sizeof(*pdev_info), GFP_KERNEL|GFP_DMA);
187377266186SHannes Reinecke 		if (!pdev_info)
187477266186SHannes Reinecke 			return -ENOMEM;
187577266186SHannes Reinecke 
187677266186SHannes Reinecke 		status = myrs_get_pdev_info(cs, sdev->channel,
187777266186SHannes Reinecke 					    sdev->id, sdev->lun,
187877266186SHannes Reinecke 					    pdev_info);
187977266186SHannes Reinecke 		if (status != MYRS_STATUS_SUCCESS) {
188077266186SHannes Reinecke 			sdev->hostdata = NULL;
188177266186SHannes Reinecke 			kfree(pdev_info);
188277266186SHannes Reinecke 			return -ENXIO;
188377266186SHannes Reinecke 		}
188477266186SHannes Reinecke 		sdev->hostdata = pdev_info;
188577266186SHannes Reinecke 	}
188677266186SHannes Reinecke 	return 0;
188777266186SHannes Reinecke }
188877266186SHannes Reinecke 
188977266186SHannes Reinecke static int myrs_slave_configure(struct scsi_device *sdev)
189077266186SHannes Reinecke {
189177266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(sdev->host);
189277266186SHannes Reinecke 	struct myrs_ldev_info *ldev_info;
189377266186SHannes Reinecke 
189477266186SHannes Reinecke 	if (sdev->channel > sdev->host->max_channel)
189577266186SHannes Reinecke 		return -ENXIO;
189677266186SHannes Reinecke 
189777266186SHannes Reinecke 	if (sdev->channel < cs->ctlr_info->physchan_present) {
189877266186SHannes Reinecke 		/* Skip HBA device */
189977266186SHannes Reinecke 		if (sdev->type == TYPE_RAID)
190077266186SHannes Reinecke 			return -ENXIO;
190177266186SHannes Reinecke 		sdev->no_uld_attach = 1;
190277266186SHannes Reinecke 		return 0;
190377266186SHannes Reinecke 	}
190477266186SHannes Reinecke 	if (sdev->lun != 0)
190577266186SHannes Reinecke 		return -ENXIO;
190677266186SHannes Reinecke 
190777266186SHannes Reinecke 	ldev_info = sdev->hostdata;
190877266186SHannes Reinecke 	if (!ldev_info)
190977266186SHannes Reinecke 		return -ENXIO;
191077266186SHannes Reinecke 	if (ldev_info->ldev_control.wce == MYRS_WRITECACHE_ENABLED ||
191177266186SHannes Reinecke 	    ldev_info->ldev_control.wce == MYRS_INTELLIGENT_WRITECACHE_ENABLED)
191277266186SHannes Reinecke 		sdev->wce_default_on = 1;
191377266186SHannes Reinecke 	sdev->tagged_supported = 1;
191477266186SHannes Reinecke 	return 0;
191577266186SHannes Reinecke }
191677266186SHannes Reinecke 
191777266186SHannes Reinecke static void myrs_slave_destroy(struct scsi_device *sdev)
191877266186SHannes Reinecke {
191977266186SHannes Reinecke 	kfree(sdev->hostdata);
192077266186SHannes Reinecke }
192177266186SHannes Reinecke 
192277266186SHannes Reinecke struct scsi_host_template myrs_template = {
192377266186SHannes Reinecke 	.module			= THIS_MODULE,
192477266186SHannes Reinecke 	.name			= "DAC960",
192577266186SHannes Reinecke 	.proc_name		= "myrs",
192677266186SHannes Reinecke 	.queuecommand		= myrs_queuecommand,
192777266186SHannes Reinecke 	.eh_host_reset_handler	= myrs_host_reset,
192877266186SHannes Reinecke 	.slave_alloc		= myrs_slave_alloc,
192977266186SHannes Reinecke 	.slave_configure	= myrs_slave_configure,
193077266186SHannes Reinecke 	.slave_destroy		= myrs_slave_destroy,
193177266186SHannes Reinecke 	.cmd_size		= sizeof(struct myrs_cmdblk),
193277266186SHannes Reinecke 	.shost_attrs		= myrs_shost_attrs,
193377266186SHannes Reinecke 	.sdev_attrs		= myrs_sdev_attrs,
193477266186SHannes Reinecke 	.this_id		= -1,
193577266186SHannes Reinecke };
193677266186SHannes Reinecke 
193777266186SHannes Reinecke static struct myrs_hba *myrs_alloc_host(struct pci_dev *pdev,
193877266186SHannes Reinecke 		const struct pci_device_id *entry)
193977266186SHannes Reinecke {
194077266186SHannes Reinecke 	struct Scsi_Host *shost;
194177266186SHannes Reinecke 	struct myrs_hba *cs;
194277266186SHannes Reinecke 
194377266186SHannes Reinecke 	shost = scsi_host_alloc(&myrs_template, sizeof(struct myrs_hba));
194477266186SHannes Reinecke 	if (!shost)
194577266186SHannes Reinecke 		return NULL;
194677266186SHannes Reinecke 
194777266186SHannes Reinecke 	shost->max_cmd_len = 16;
194877266186SHannes Reinecke 	shost->max_lun = 256;
194977266186SHannes Reinecke 	cs = shost_priv(shost);
195077266186SHannes Reinecke 	mutex_init(&cs->dcmd_mutex);
195177266186SHannes Reinecke 	mutex_init(&cs->cinfo_mutex);
195277266186SHannes Reinecke 	cs->host = shost;
195377266186SHannes Reinecke 
195477266186SHannes Reinecke 	return cs;
195577266186SHannes Reinecke }
195677266186SHannes Reinecke 
195777266186SHannes Reinecke /*
195877266186SHannes Reinecke  * RAID template functions
195977266186SHannes Reinecke  */
196077266186SHannes Reinecke 
196177266186SHannes Reinecke /**
196277266186SHannes Reinecke  * myrs_is_raid - return boolean indicating device is raid volume
196377266186SHannes Reinecke  * @dev the device struct object
196477266186SHannes Reinecke  */
196577266186SHannes Reinecke static int
196677266186SHannes Reinecke myrs_is_raid(struct device *dev)
196777266186SHannes Reinecke {
196877266186SHannes Reinecke 	struct scsi_device *sdev = to_scsi_device(dev);
196977266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(sdev->host);
197077266186SHannes Reinecke 
197177266186SHannes Reinecke 	return (sdev->channel >= cs->ctlr_info->physchan_present) ? 1 : 0;
197277266186SHannes Reinecke }
197377266186SHannes Reinecke 
197477266186SHannes Reinecke /**
197577266186SHannes Reinecke  * myrs_get_resync - get raid volume resync percent complete
197677266186SHannes Reinecke  * @dev the device struct object
197777266186SHannes Reinecke  */
197877266186SHannes Reinecke static void
197977266186SHannes Reinecke myrs_get_resync(struct device *dev)
198077266186SHannes Reinecke {
198177266186SHannes Reinecke 	struct scsi_device *sdev = to_scsi_device(dev);
198277266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(sdev->host);
198377266186SHannes Reinecke 	struct myrs_ldev_info *ldev_info = sdev->hostdata;
1984d592dd64SJames Bottomley 	u64 percent_complete = 0;
1985d592dd64SJames Bottomley 	u8 status;
198677266186SHannes Reinecke 
198777266186SHannes Reinecke 	if (sdev->channel < cs->ctlr_info->physchan_present || !ldev_info)
198877266186SHannes Reinecke 		return;
198977266186SHannes Reinecke 	if (ldev_info->rbld_active) {
199077266186SHannes Reinecke 		unsigned short ldev_num = ldev_info->ldev_num;
199177266186SHannes Reinecke 
199277266186SHannes Reinecke 		status = myrs_get_ldev_info(cs, ldev_num, ldev_info);
1993d592dd64SJames Bottomley 		percent_complete = ldev_info->rbld_lba * 100;
1994d592dd64SJames Bottomley 		do_div(percent_complete, ldev_info->cfg_devsize);
199577266186SHannes Reinecke 	}
199677266186SHannes Reinecke 	raid_set_resync(myrs_raid_template, dev, percent_complete);
199777266186SHannes Reinecke }
199877266186SHannes Reinecke 
199977266186SHannes Reinecke /**
200077266186SHannes Reinecke  * myrs_get_state - get raid volume status
200177266186SHannes Reinecke  * @dev the device struct object
200277266186SHannes Reinecke  */
200377266186SHannes Reinecke static void
200477266186SHannes Reinecke myrs_get_state(struct device *dev)
200577266186SHannes Reinecke {
200677266186SHannes Reinecke 	struct scsi_device *sdev = to_scsi_device(dev);
200777266186SHannes Reinecke 	struct myrs_hba *cs = shost_priv(sdev->host);
200877266186SHannes Reinecke 	struct myrs_ldev_info *ldev_info = sdev->hostdata;
200977266186SHannes Reinecke 	enum raid_state state = RAID_STATE_UNKNOWN;
201077266186SHannes Reinecke 
201177266186SHannes Reinecke 	if (sdev->channel < cs->ctlr_info->physchan_present || !ldev_info)
201277266186SHannes Reinecke 		state = RAID_STATE_UNKNOWN;
201377266186SHannes Reinecke 	else {
201477266186SHannes Reinecke 		switch (ldev_info->dev_state) {
201577266186SHannes Reinecke 		case MYRS_DEVICE_ONLINE:
201677266186SHannes Reinecke 			state = RAID_STATE_ACTIVE;
201777266186SHannes Reinecke 			break;
201877266186SHannes Reinecke 		case MYRS_DEVICE_SUSPECTED_CRITICAL:
201977266186SHannes Reinecke 		case MYRS_DEVICE_CRITICAL:
202077266186SHannes Reinecke 			state = RAID_STATE_DEGRADED;
202177266186SHannes Reinecke 			break;
202277266186SHannes Reinecke 		case MYRS_DEVICE_REBUILD:
202377266186SHannes Reinecke 			state = RAID_STATE_RESYNCING;
202477266186SHannes Reinecke 			break;
202577266186SHannes Reinecke 		case MYRS_DEVICE_UNCONFIGURED:
202677266186SHannes Reinecke 		case MYRS_DEVICE_INVALID_STATE:
202777266186SHannes Reinecke 			state = RAID_STATE_UNKNOWN;
202877266186SHannes Reinecke 			break;
202977266186SHannes Reinecke 		default:
203077266186SHannes Reinecke 			state = RAID_STATE_OFFLINE;
203177266186SHannes Reinecke 		}
203277266186SHannes Reinecke 	}
203377266186SHannes Reinecke 	raid_set_state(myrs_raid_template, dev, state);
203477266186SHannes Reinecke }
203577266186SHannes Reinecke 
203677266186SHannes Reinecke struct raid_function_template myrs_raid_functions = {
203777266186SHannes Reinecke 	.cookie		= &myrs_template,
203877266186SHannes Reinecke 	.is_raid	= myrs_is_raid,
203977266186SHannes Reinecke 	.get_resync	= myrs_get_resync,
204077266186SHannes Reinecke 	.get_state	= myrs_get_state,
204177266186SHannes Reinecke };
204277266186SHannes Reinecke 
204377266186SHannes Reinecke /*
204477266186SHannes Reinecke  * PCI interface functions
204577266186SHannes Reinecke  */
204677266186SHannes Reinecke void myrs_flush_cache(struct myrs_hba *cs)
204777266186SHannes Reinecke {
204877266186SHannes Reinecke 	myrs_dev_op(cs, MYRS_IOCTL_FLUSH_DEVICE_DATA, MYRS_RAID_CONTROLLER);
204977266186SHannes Reinecke }
205077266186SHannes Reinecke 
205177266186SHannes Reinecke static void myrs_handle_scsi(struct myrs_hba *cs, struct myrs_cmdblk *cmd_blk,
205277266186SHannes Reinecke 		struct scsi_cmnd *scmd)
205377266186SHannes Reinecke {
205477266186SHannes Reinecke 	unsigned char status;
205577266186SHannes Reinecke 
205677266186SHannes Reinecke 	if (!cmd_blk)
205777266186SHannes Reinecke 		return;
205877266186SHannes Reinecke 
205977266186SHannes Reinecke 	scsi_dma_unmap(scmd);
206077266186SHannes Reinecke 	status = cmd_blk->status;
206177266186SHannes Reinecke 	if (cmd_blk->sense) {
206277266186SHannes Reinecke 		if (status == MYRS_STATUS_FAILED && cmd_blk->sense_len) {
206377266186SHannes Reinecke 			unsigned int sense_len = SCSI_SENSE_BUFFERSIZE;
206477266186SHannes Reinecke 
206577266186SHannes Reinecke 			if (sense_len > cmd_blk->sense_len)
206677266186SHannes Reinecke 				sense_len = cmd_blk->sense_len;
206777266186SHannes Reinecke 			memcpy(scmd->sense_buffer, cmd_blk->sense, sense_len);
206877266186SHannes Reinecke 		}
206977266186SHannes Reinecke 		dma_pool_free(cs->sense_pool, cmd_blk->sense,
207077266186SHannes Reinecke 			      cmd_blk->sense_addr);
207177266186SHannes Reinecke 		cmd_blk->sense = NULL;
207277266186SHannes Reinecke 		cmd_blk->sense_addr = 0;
207377266186SHannes Reinecke 	}
207477266186SHannes Reinecke 	if (cmd_blk->dcdb) {
207577266186SHannes Reinecke 		dma_pool_free(cs->dcdb_pool, cmd_blk->dcdb,
207677266186SHannes Reinecke 			      cmd_blk->dcdb_dma);
207777266186SHannes Reinecke 		cmd_blk->dcdb = NULL;
207877266186SHannes Reinecke 		cmd_blk->dcdb_dma = 0;
207977266186SHannes Reinecke 	}
208077266186SHannes Reinecke 	if (cmd_blk->sgl) {
208177266186SHannes Reinecke 		dma_pool_free(cs->sg_pool, cmd_blk->sgl,
208277266186SHannes Reinecke 			      cmd_blk->sgl_addr);
208377266186SHannes Reinecke 		cmd_blk->sgl = NULL;
208477266186SHannes Reinecke 		cmd_blk->sgl_addr = 0;
208577266186SHannes Reinecke 	}
208677266186SHannes Reinecke 	if (cmd_blk->residual)
208777266186SHannes Reinecke 		scsi_set_resid(scmd, cmd_blk->residual);
208877266186SHannes Reinecke 	if (status == MYRS_STATUS_DEVICE_NON_RESPONSIVE ||
208977266186SHannes Reinecke 	    status == MYRS_STATUS_DEVICE_NON_RESPONSIVE2)
209077266186SHannes Reinecke 		scmd->result = (DID_BAD_TARGET << 16);
209177266186SHannes Reinecke 	else
20929a231caaSDan Carpenter 		scmd->result = (DID_OK << 16) | status;
209377266186SHannes Reinecke 	scmd->scsi_done(scmd);
209477266186SHannes Reinecke }
209577266186SHannes Reinecke 
209677266186SHannes Reinecke static void myrs_handle_cmdblk(struct myrs_hba *cs, struct myrs_cmdblk *cmd_blk)
209777266186SHannes Reinecke {
209877266186SHannes Reinecke 	if (!cmd_blk)
209977266186SHannes Reinecke 		return;
210077266186SHannes Reinecke 
210177266186SHannes Reinecke 	if (cmd_blk->complete) {
210277266186SHannes Reinecke 		complete(cmd_blk->complete);
210377266186SHannes Reinecke 		cmd_blk->complete = NULL;
210477266186SHannes Reinecke 	}
210577266186SHannes Reinecke }
210677266186SHannes Reinecke 
210777266186SHannes Reinecke static void myrs_monitor(struct work_struct *work)
210877266186SHannes Reinecke {
210977266186SHannes Reinecke 	struct myrs_hba *cs = container_of(work, struct myrs_hba,
211077266186SHannes Reinecke 					   monitor_work.work);
211177266186SHannes Reinecke 	struct Scsi_Host *shost = cs->host;
211277266186SHannes Reinecke 	struct myrs_ctlr_info *info = cs->ctlr_info;
211377266186SHannes Reinecke 	unsigned int epoch = cs->fwstat_buf->epoch;
211477266186SHannes Reinecke 	unsigned long interval = MYRS_PRIMARY_MONITOR_INTERVAL;
211577266186SHannes Reinecke 	unsigned char status;
211677266186SHannes Reinecke 
211777266186SHannes Reinecke 	dev_dbg(&shost->shost_gendev, "monitor tick\n");
211877266186SHannes Reinecke 
211977266186SHannes Reinecke 	status = myrs_get_fwstatus(cs);
212077266186SHannes Reinecke 
212177266186SHannes Reinecke 	if (cs->needs_update) {
212277266186SHannes Reinecke 		cs->needs_update = false;
212377266186SHannes Reinecke 		mutex_lock(&cs->cinfo_mutex);
212477266186SHannes Reinecke 		status = myrs_get_ctlr_info(cs);
212577266186SHannes Reinecke 		mutex_unlock(&cs->cinfo_mutex);
212677266186SHannes Reinecke 	}
212777266186SHannes Reinecke 	if (cs->fwstat_buf->next_evseq - cs->next_evseq > 0) {
212877266186SHannes Reinecke 		status = myrs_get_event(cs, cs->next_evseq,
212977266186SHannes Reinecke 					cs->event_buf);
213077266186SHannes Reinecke 		if (status == MYRS_STATUS_SUCCESS) {
213177266186SHannes Reinecke 			myrs_log_event(cs, cs->event_buf);
213277266186SHannes Reinecke 			cs->next_evseq++;
213377266186SHannes Reinecke 			interval = 1;
213477266186SHannes Reinecke 		}
213577266186SHannes Reinecke 	}
213677266186SHannes Reinecke 
213777266186SHannes Reinecke 	if (time_after(jiffies, cs->secondary_monitor_time
213877266186SHannes Reinecke 		       + MYRS_SECONDARY_MONITOR_INTERVAL))
213977266186SHannes Reinecke 		cs->secondary_monitor_time = jiffies;
214077266186SHannes Reinecke 
214177266186SHannes Reinecke 	if (info->bg_init_active +
214277266186SHannes Reinecke 	    info->ldev_init_active +
214377266186SHannes Reinecke 	    info->pdev_init_active +
214477266186SHannes Reinecke 	    info->cc_active +
214577266186SHannes Reinecke 	    info->rbld_active +
214677266186SHannes Reinecke 	    info->exp_active != 0) {
214777266186SHannes Reinecke 		struct scsi_device *sdev;
214877266186SHannes Reinecke 
214977266186SHannes Reinecke 		shost_for_each_device(sdev, shost) {
215077266186SHannes Reinecke 			struct myrs_ldev_info *ldev_info;
215177266186SHannes Reinecke 			int ldev_num;
215277266186SHannes Reinecke 
215377266186SHannes Reinecke 			if (sdev->channel < info->physchan_present)
215477266186SHannes Reinecke 				continue;
215577266186SHannes Reinecke 			ldev_info = sdev->hostdata;
215677266186SHannes Reinecke 			if (!ldev_info)
215777266186SHannes Reinecke 				continue;
215877266186SHannes Reinecke 			ldev_num = ldev_info->ldev_num;
215977266186SHannes Reinecke 			myrs_get_ldev_info(cs, ldev_num, ldev_info);
216077266186SHannes Reinecke 		}
216177266186SHannes Reinecke 		cs->needs_update = true;
216277266186SHannes Reinecke 	}
216377266186SHannes Reinecke 	if (epoch == cs->epoch &&
216477266186SHannes Reinecke 	    cs->fwstat_buf->next_evseq == cs->next_evseq &&
216577266186SHannes Reinecke 	    (cs->needs_update == false ||
216677266186SHannes Reinecke 	     time_before(jiffies, cs->primary_monitor_time
216777266186SHannes Reinecke 			 + MYRS_PRIMARY_MONITOR_INTERVAL))) {
216877266186SHannes Reinecke 		interval = MYRS_SECONDARY_MONITOR_INTERVAL;
216977266186SHannes Reinecke 	}
217077266186SHannes Reinecke 
217177266186SHannes Reinecke 	if (interval > 1)
217277266186SHannes Reinecke 		cs->primary_monitor_time = jiffies;
217377266186SHannes Reinecke 	queue_delayed_work(cs->work_q, &cs->monitor_work, interval);
217477266186SHannes Reinecke }
217577266186SHannes Reinecke 
217677266186SHannes Reinecke static bool myrs_create_mempools(struct pci_dev *pdev, struct myrs_hba *cs)
217777266186SHannes Reinecke {
217877266186SHannes Reinecke 	struct Scsi_Host *shost = cs->host;
217977266186SHannes Reinecke 	size_t elem_size, elem_align;
218077266186SHannes Reinecke 
218177266186SHannes Reinecke 	elem_align = sizeof(struct myrs_sge);
218277266186SHannes Reinecke 	elem_size = shost->sg_tablesize * elem_align;
218377266186SHannes Reinecke 	cs->sg_pool = dma_pool_create("myrs_sg", &pdev->dev,
218477266186SHannes Reinecke 				      elem_size, elem_align, 0);
218577266186SHannes Reinecke 	if (cs->sg_pool == NULL) {
218677266186SHannes Reinecke 		shost_printk(KERN_ERR, shost,
218777266186SHannes Reinecke 			     "Failed to allocate SG pool\n");
218877266186SHannes Reinecke 		return false;
218977266186SHannes Reinecke 	}
219077266186SHannes Reinecke 
219177266186SHannes Reinecke 	cs->sense_pool = dma_pool_create("myrs_sense", &pdev->dev,
219277266186SHannes Reinecke 					 MYRS_SENSE_SIZE, sizeof(int), 0);
219377266186SHannes Reinecke 	if (cs->sense_pool == NULL) {
219477266186SHannes Reinecke 		dma_pool_destroy(cs->sg_pool);
219577266186SHannes Reinecke 		cs->sg_pool = NULL;
219677266186SHannes Reinecke 		shost_printk(KERN_ERR, shost,
219777266186SHannes Reinecke 			     "Failed to allocate sense data pool\n");
219877266186SHannes Reinecke 		return false;
219977266186SHannes Reinecke 	}
220077266186SHannes Reinecke 
220177266186SHannes Reinecke 	cs->dcdb_pool = dma_pool_create("myrs_dcdb", &pdev->dev,
220277266186SHannes Reinecke 					MYRS_DCDB_SIZE,
220377266186SHannes Reinecke 					sizeof(unsigned char), 0);
220477266186SHannes Reinecke 	if (!cs->dcdb_pool) {
220577266186SHannes Reinecke 		dma_pool_destroy(cs->sg_pool);
220677266186SHannes Reinecke 		cs->sg_pool = NULL;
220777266186SHannes Reinecke 		dma_pool_destroy(cs->sense_pool);
220877266186SHannes Reinecke 		cs->sense_pool = NULL;
220977266186SHannes Reinecke 		shost_printk(KERN_ERR, shost,
221077266186SHannes Reinecke 			     "Failed to allocate DCDB pool\n");
221177266186SHannes Reinecke 		return false;
221277266186SHannes Reinecke 	}
221377266186SHannes Reinecke 
221477266186SHannes Reinecke 	snprintf(cs->work_q_name, sizeof(cs->work_q_name),
221577266186SHannes Reinecke 		 "myrs_wq_%d", shost->host_no);
221677266186SHannes Reinecke 	cs->work_q = create_singlethread_workqueue(cs->work_q_name);
221777266186SHannes Reinecke 	if (!cs->work_q) {
221877266186SHannes Reinecke 		dma_pool_destroy(cs->dcdb_pool);
221977266186SHannes Reinecke 		cs->dcdb_pool = NULL;
222077266186SHannes Reinecke 		dma_pool_destroy(cs->sg_pool);
222177266186SHannes Reinecke 		cs->sg_pool = NULL;
222277266186SHannes Reinecke 		dma_pool_destroy(cs->sense_pool);
222377266186SHannes Reinecke 		cs->sense_pool = NULL;
222477266186SHannes Reinecke 		shost_printk(KERN_ERR, shost,
222577266186SHannes Reinecke 			     "Failed to create workqueue\n");
222677266186SHannes Reinecke 		return false;
222777266186SHannes Reinecke 	}
222877266186SHannes Reinecke 
222977266186SHannes Reinecke 	/* Initialize the Monitoring Timer. */
223077266186SHannes Reinecke 	INIT_DELAYED_WORK(&cs->monitor_work, myrs_monitor);
223177266186SHannes Reinecke 	queue_delayed_work(cs->work_q, &cs->monitor_work, 1);
223277266186SHannes Reinecke 
223377266186SHannes Reinecke 	return true;
223477266186SHannes Reinecke }
223577266186SHannes Reinecke 
223677266186SHannes Reinecke static void myrs_destroy_mempools(struct myrs_hba *cs)
223777266186SHannes Reinecke {
223877266186SHannes Reinecke 	cancel_delayed_work_sync(&cs->monitor_work);
223977266186SHannes Reinecke 	destroy_workqueue(cs->work_q);
224077266186SHannes Reinecke 
224177266186SHannes Reinecke 	dma_pool_destroy(cs->sg_pool);
224277266186SHannes Reinecke 	dma_pool_destroy(cs->dcdb_pool);
224377266186SHannes Reinecke 	dma_pool_destroy(cs->sense_pool);
224477266186SHannes Reinecke }
224577266186SHannes Reinecke 
224677266186SHannes Reinecke static void myrs_unmap(struct myrs_hba *cs)
224777266186SHannes Reinecke {
224877266186SHannes Reinecke 	kfree(cs->event_buf);
224977266186SHannes Reinecke 	kfree(cs->ctlr_info);
225077266186SHannes Reinecke 	if (cs->fwstat_buf) {
225177266186SHannes Reinecke 		dma_free_coherent(&cs->pdev->dev, sizeof(struct myrs_fwstat),
225277266186SHannes Reinecke 				  cs->fwstat_buf, cs->fwstat_addr);
225377266186SHannes Reinecke 		cs->fwstat_buf = NULL;
225477266186SHannes Reinecke 	}
225577266186SHannes Reinecke 	if (cs->first_stat_mbox) {
225677266186SHannes Reinecke 		dma_free_coherent(&cs->pdev->dev, cs->stat_mbox_size,
225777266186SHannes Reinecke 				  cs->first_stat_mbox, cs->stat_mbox_addr);
225877266186SHannes Reinecke 		cs->first_stat_mbox = NULL;
225977266186SHannes Reinecke 	}
226077266186SHannes Reinecke 	if (cs->first_cmd_mbox) {
226177266186SHannes Reinecke 		dma_free_coherent(&cs->pdev->dev, cs->cmd_mbox_size,
226277266186SHannes Reinecke 				  cs->first_cmd_mbox, cs->cmd_mbox_addr);
226377266186SHannes Reinecke 		cs->first_cmd_mbox = NULL;
226477266186SHannes Reinecke 	}
226577266186SHannes Reinecke }
226677266186SHannes Reinecke 
226777266186SHannes Reinecke static void myrs_cleanup(struct myrs_hba *cs)
226877266186SHannes Reinecke {
226977266186SHannes Reinecke 	struct pci_dev *pdev = cs->pdev;
227077266186SHannes Reinecke 
227177266186SHannes Reinecke 	/* Free the memory mailbox, status, and related structures */
227277266186SHannes Reinecke 	myrs_unmap(cs);
227377266186SHannes Reinecke 
227477266186SHannes Reinecke 	if (cs->mmio_base) {
227577266186SHannes Reinecke 		cs->disable_intr(cs);
227677266186SHannes Reinecke 		iounmap(cs->mmio_base);
227777266186SHannes Reinecke 	}
227877266186SHannes Reinecke 	if (cs->irq)
227977266186SHannes Reinecke 		free_irq(cs->irq, cs);
228077266186SHannes Reinecke 	if (cs->io_addr)
228177266186SHannes Reinecke 		release_region(cs->io_addr, 0x80);
228277266186SHannes Reinecke 	iounmap(cs->mmio_base);
228377266186SHannes Reinecke 	pci_set_drvdata(pdev, NULL);
228477266186SHannes Reinecke 	pci_disable_device(pdev);
228577266186SHannes Reinecke 	scsi_host_put(cs->host);
228677266186SHannes Reinecke }
228777266186SHannes Reinecke 
228877266186SHannes Reinecke static struct myrs_hba *myrs_detect(struct pci_dev *pdev,
228977266186SHannes Reinecke 		const struct pci_device_id *entry)
229077266186SHannes Reinecke {
229177266186SHannes Reinecke 	struct myrs_privdata *privdata =
229277266186SHannes Reinecke 		(struct myrs_privdata *)entry->driver_data;
229377266186SHannes Reinecke 	irq_handler_t irq_handler = privdata->irq_handler;
229477266186SHannes Reinecke 	unsigned int mmio_size = privdata->mmio_size;
229577266186SHannes Reinecke 	struct myrs_hba *cs = NULL;
229677266186SHannes Reinecke 
229777266186SHannes Reinecke 	cs = myrs_alloc_host(pdev, entry);
229877266186SHannes Reinecke 	if (!cs) {
229977266186SHannes Reinecke 		dev_err(&pdev->dev, "Unable to allocate Controller\n");
230077266186SHannes Reinecke 		return NULL;
230177266186SHannes Reinecke 	}
230277266186SHannes Reinecke 	cs->pdev = pdev;
230377266186SHannes Reinecke 
230477266186SHannes Reinecke 	if (pci_enable_device(pdev))
230577266186SHannes Reinecke 		goto Failure;
230677266186SHannes Reinecke 
230777266186SHannes Reinecke 	cs->pci_addr = pci_resource_start(pdev, 0);
230877266186SHannes Reinecke 
230977266186SHannes Reinecke 	pci_set_drvdata(pdev, cs);
231077266186SHannes Reinecke 	spin_lock_init(&cs->queue_lock);
231177266186SHannes Reinecke 	/* Map the Controller Register Window. */
231277266186SHannes Reinecke 	if (mmio_size < PAGE_SIZE)
231377266186SHannes Reinecke 		mmio_size = PAGE_SIZE;
2314*4bdc0d67SChristoph Hellwig 	cs->mmio_base = ioremap(cs->pci_addr & PAGE_MASK, mmio_size);
231577266186SHannes Reinecke 	if (cs->mmio_base == NULL) {
231677266186SHannes Reinecke 		dev_err(&pdev->dev,
231777266186SHannes Reinecke 			"Unable to map Controller Register Window\n");
231877266186SHannes Reinecke 		goto Failure;
231977266186SHannes Reinecke 	}
232077266186SHannes Reinecke 
232177266186SHannes Reinecke 	cs->io_base = cs->mmio_base + (cs->pci_addr & ~PAGE_MASK);
232277266186SHannes Reinecke 	if (privdata->hw_init(pdev, cs, cs->io_base))
232377266186SHannes Reinecke 		goto Failure;
232477266186SHannes Reinecke 
232577266186SHannes Reinecke 	/* Acquire shared access to the IRQ Channel. */
232677266186SHannes Reinecke 	if (request_irq(pdev->irq, irq_handler, IRQF_SHARED, "myrs", cs) < 0) {
232777266186SHannes Reinecke 		dev_err(&pdev->dev,
232877266186SHannes Reinecke 			"Unable to acquire IRQ Channel %d\n", pdev->irq);
232977266186SHannes Reinecke 		goto Failure;
233077266186SHannes Reinecke 	}
233177266186SHannes Reinecke 	cs->irq = pdev->irq;
233277266186SHannes Reinecke 	return cs;
233377266186SHannes Reinecke 
233477266186SHannes Reinecke Failure:
233577266186SHannes Reinecke 	dev_err(&pdev->dev,
233677266186SHannes Reinecke 		"Failed to initialize Controller\n");
233777266186SHannes Reinecke 	myrs_cleanup(cs);
233877266186SHannes Reinecke 	return NULL;
233977266186SHannes Reinecke }
234077266186SHannes Reinecke 
234177266186SHannes Reinecke /**
234277266186SHannes Reinecke  * myrs_err_status reports Controller BIOS Messages passed through
234377266186SHannes Reinecke   the Error Status Register when the driver performs the BIOS handshaking.
234477266186SHannes Reinecke   It returns true for fatal errors and false otherwise.
234577266186SHannes Reinecke */
234677266186SHannes Reinecke 
234777266186SHannes Reinecke static bool myrs_err_status(struct myrs_hba *cs, unsigned char status,
234877266186SHannes Reinecke 		unsigned char parm0, unsigned char parm1)
234977266186SHannes Reinecke {
235077266186SHannes Reinecke 	struct pci_dev *pdev = cs->pdev;
235177266186SHannes Reinecke 
235277266186SHannes Reinecke 	switch (status) {
235377266186SHannes Reinecke 	case 0x00:
235477266186SHannes Reinecke 		dev_info(&pdev->dev,
235577266186SHannes Reinecke 			 "Physical Device %d:%d Not Responding\n",
235677266186SHannes Reinecke 			 parm1, parm0);
235777266186SHannes Reinecke 		break;
235877266186SHannes Reinecke 	case 0x08:
235977266186SHannes Reinecke 		dev_notice(&pdev->dev, "Spinning Up Drives\n");
236077266186SHannes Reinecke 		break;
236177266186SHannes Reinecke 	case 0x30:
236277266186SHannes Reinecke 		dev_notice(&pdev->dev, "Configuration Checksum Error\n");
236377266186SHannes Reinecke 		break;
236477266186SHannes Reinecke 	case 0x60:
236577266186SHannes Reinecke 		dev_notice(&pdev->dev, "Mirror Race Recovery Failed\n");
236677266186SHannes Reinecke 		break;
236777266186SHannes Reinecke 	case 0x70:
236877266186SHannes Reinecke 		dev_notice(&pdev->dev, "Mirror Race Recovery In Progress\n");
236977266186SHannes Reinecke 		break;
237077266186SHannes Reinecke 	case 0x90:
237177266186SHannes Reinecke 		dev_notice(&pdev->dev, "Physical Device %d:%d COD Mismatch\n",
237277266186SHannes Reinecke 			   parm1, parm0);
237377266186SHannes Reinecke 		break;
237477266186SHannes Reinecke 	case 0xA0:
237577266186SHannes Reinecke 		dev_notice(&pdev->dev, "Logical Drive Installation Aborted\n");
237677266186SHannes Reinecke 		break;
237777266186SHannes Reinecke 	case 0xB0:
237877266186SHannes Reinecke 		dev_notice(&pdev->dev, "Mirror Race On A Critical Logical Drive\n");
237977266186SHannes Reinecke 		break;
238077266186SHannes Reinecke 	case 0xD0:
238177266186SHannes Reinecke 		dev_notice(&pdev->dev, "New Controller Configuration Found\n");
238277266186SHannes Reinecke 		break;
238377266186SHannes Reinecke 	case 0xF0:
238477266186SHannes Reinecke 		dev_err(&pdev->dev, "Fatal Memory Parity Error\n");
238577266186SHannes Reinecke 		return true;
238677266186SHannes Reinecke 	default:
238777266186SHannes Reinecke 		dev_err(&pdev->dev, "Unknown Initialization Error %02X\n",
238877266186SHannes Reinecke 			status);
238977266186SHannes Reinecke 		return true;
239077266186SHannes Reinecke 	}
239177266186SHannes Reinecke 	return false;
239277266186SHannes Reinecke }
239377266186SHannes Reinecke 
239477266186SHannes Reinecke /*
239577266186SHannes Reinecke  * Hardware-specific functions
239677266186SHannes Reinecke  */
239777266186SHannes Reinecke 
239877266186SHannes Reinecke /*
239977266186SHannes Reinecke  * DAC960 GEM Series Controllers.
240077266186SHannes Reinecke  */
240177266186SHannes Reinecke 
240277266186SHannes Reinecke static inline void DAC960_GEM_hw_mbox_new_cmd(void __iomem *base)
240377266186SHannes Reinecke {
240477266186SHannes Reinecke 	__le32 val = cpu_to_le32(DAC960_GEM_IDB_HWMBOX_NEW_CMD << 24);
240577266186SHannes Reinecke 
240677266186SHannes Reinecke 	writel(val, base + DAC960_GEM_IDB_READ_OFFSET);
240777266186SHannes Reinecke }
240877266186SHannes Reinecke 
240977266186SHannes Reinecke static inline void DAC960_GEM_ack_hw_mbox_status(void __iomem *base)
241077266186SHannes Reinecke {
241177266186SHannes Reinecke 	__le32 val = cpu_to_le32(DAC960_GEM_IDB_HWMBOX_ACK_STS << 24);
241277266186SHannes Reinecke 
241377266186SHannes Reinecke 	writel(val, base + DAC960_GEM_IDB_CLEAR_OFFSET);
241477266186SHannes Reinecke }
241577266186SHannes Reinecke 
241677266186SHannes Reinecke static inline void DAC960_GEM_gen_intr(void __iomem *base)
241777266186SHannes Reinecke {
241877266186SHannes Reinecke 	__le32 val = cpu_to_le32(DAC960_GEM_IDB_GEN_IRQ << 24);
241977266186SHannes Reinecke 
242077266186SHannes Reinecke 	writel(val, base + DAC960_GEM_IDB_READ_OFFSET);
242177266186SHannes Reinecke }
242277266186SHannes Reinecke 
242377266186SHannes Reinecke static inline void DAC960_GEM_reset_ctrl(void __iomem *base)
242477266186SHannes Reinecke {
242577266186SHannes Reinecke 	__le32 val = cpu_to_le32(DAC960_GEM_IDB_CTRL_RESET << 24);
242677266186SHannes Reinecke 
242777266186SHannes Reinecke 	writel(val, base + DAC960_GEM_IDB_READ_OFFSET);
242877266186SHannes Reinecke }
242977266186SHannes Reinecke 
243077266186SHannes Reinecke static inline void DAC960_GEM_mem_mbox_new_cmd(void __iomem *base)
243177266186SHannes Reinecke {
243277266186SHannes Reinecke 	__le32 val = cpu_to_le32(DAC960_GEM_IDB_HWMBOX_NEW_CMD << 24);
243377266186SHannes Reinecke 
243477266186SHannes Reinecke 	writel(val, base + DAC960_GEM_IDB_READ_OFFSET);
243577266186SHannes Reinecke }
243677266186SHannes Reinecke 
243777266186SHannes Reinecke static inline bool DAC960_GEM_hw_mbox_is_full(void __iomem *base)
243877266186SHannes Reinecke {
243977266186SHannes Reinecke 	__le32 val;
244077266186SHannes Reinecke 
244177266186SHannes Reinecke 	val = readl(base + DAC960_GEM_IDB_READ_OFFSET);
244277266186SHannes Reinecke 	return (le32_to_cpu(val) >> 24) & DAC960_GEM_IDB_HWMBOX_FULL;
244377266186SHannes Reinecke }
244477266186SHannes Reinecke 
244577266186SHannes Reinecke static inline bool DAC960_GEM_init_in_progress(void __iomem *base)
244677266186SHannes Reinecke {
244777266186SHannes Reinecke 	__le32 val;
244877266186SHannes Reinecke 
244977266186SHannes Reinecke 	val = readl(base + DAC960_GEM_IDB_READ_OFFSET);
245077266186SHannes Reinecke 	return (le32_to_cpu(val) >> 24) & DAC960_GEM_IDB_INIT_IN_PROGRESS;
245177266186SHannes Reinecke }
245277266186SHannes Reinecke 
245377266186SHannes Reinecke static inline void DAC960_GEM_ack_hw_mbox_intr(void __iomem *base)
245477266186SHannes Reinecke {
245577266186SHannes Reinecke 	__le32 val = cpu_to_le32(DAC960_GEM_ODB_HWMBOX_ACK_IRQ << 24);
245677266186SHannes Reinecke 
245777266186SHannes Reinecke 	writel(val, base + DAC960_GEM_ODB_CLEAR_OFFSET);
245877266186SHannes Reinecke }
245977266186SHannes Reinecke 
246077266186SHannes Reinecke static inline void DAC960_GEM_ack_mem_mbox_intr(void __iomem *base)
246177266186SHannes Reinecke {
246277266186SHannes Reinecke 	__le32 val = cpu_to_le32(DAC960_GEM_ODB_MMBOX_ACK_IRQ << 24);
246377266186SHannes Reinecke 
246477266186SHannes Reinecke 	writel(val, base + DAC960_GEM_ODB_CLEAR_OFFSET);
246577266186SHannes Reinecke }
246677266186SHannes Reinecke 
246777266186SHannes Reinecke static inline void DAC960_GEM_ack_intr(void __iomem *base)
246877266186SHannes Reinecke {
246977266186SHannes Reinecke 	__le32 val = cpu_to_le32((DAC960_GEM_ODB_HWMBOX_ACK_IRQ |
247077266186SHannes Reinecke 				  DAC960_GEM_ODB_MMBOX_ACK_IRQ) << 24);
247177266186SHannes Reinecke 
247277266186SHannes Reinecke 	writel(val, base + DAC960_GEM_ODB_CLEAR_OFFSET);
247377266186SHannes Reinecke }
247477266186SHannes Reinecke 
247577266186SHannes Reinecke static inline bool DAC960_GEM_hw_mbox_status_available(void __iomem *base)
247677266186SHannes Reinecke {
247777266186SHannes Reinecke 	__le32 val;
247877266186SHannes Reinecke 
247977266186SHannes Reinecke 	val = readl(base + DAC960_GEM_ODB_READ_OFFSET);
248077266186SHannes Reinecke 	return (le32_to_cpu(val) >> 24) & DAC960_GEM_ODB_HWMBOX_STS_AVAIL;
248177266186SHannes Reinecke }
248277266186SHannes Reinecke 
248377266186SHannes Reinecke static inline bool DAC960_GEM_mem_mbox_status_available(void __iomem *base)
248477266186SHannes Reinecke {
248577266186SHannes Reinecke 	__le32 val;
248677266186SHannes Reinecke 
248777266186SHannes Reinecke 	val = readl(base + DAC960_GEM_ODB_READ_OFFSET);
248877266186SHannes Reinecke 	return (le32_to_cpu(val) >> 24) & DAC960_GEM_ODB_MMBOX_STS_AVAIL;
248977266186SHannes Reinecke }
249077266186SHannes Reinecke 
249177266186SHannes Reinecke static inline void DAC960_GEM_enable_intr(void __iomem *base)
249277266186SHannes Reinecke {
249377266186SHannes Reinecke 	__le32 val = cpu_to_le32((DAC960_GEM_IRQMASK_HWMBOX_IRQ |
249477266186SHannes Reinecke 				  DAC960_GEM_IRQMASK_MMBOX_IRQ) << 24);
249577266186SHannes Reinecke 	writel(val, base + DAC960_GEM_IRQMASK_CLEAR_OFFSET);
249677266186SHannes Reinecke }
249777266186SHannes Reinecke 
249877266186SHannes Reinecke static inline void DAC960_GEM_disable_intr(void __iomem *base)
249977266186SHannes Reinecke {
250077266186SHannes Reinecke 	__le32 val = 0;
250177266186SHannes Reinecke 
250277266186SHannes Reinecke 	writel(val, base + DAC960_GEM_IRQMASK_READ_OFFSET);
250377266186SHannes Reinecke }
250477266186SHannes Reinecke 
250577266186SHannes Reinecke static inline bool DAC960_GEM_intr_enabled(void __iomem *base)
250677266186SHannes Reinecke {
250777266186SHannes Reinecke 	__le32 val;
250877266186SHannes Reinecke 
250977266186SHannes Reinecke 	val = readl(base + DAC960_GEM_IRQMASK_READ_OFFSET);
251077266186SHannes Reinecke 	return !((le32_to_cpu(val) >> 24) &
251177266186SHannes Reinecke 		 (DAC960_GEM_IRQMASK_HWMBOX_IRQ |
251277266186SHannes Reinecke 		  DAC960_GEM_IRQMASK_MMBOX_IRQ));
251377266186SHannes Reinecke }
251477266186SHannes Reinecke 
251577266186SHannes Reinecke static inline void DAC960_GEM_write_cmd_mbox(union myrs_cmd_mbox *mem_mbox,
251677266186SHannes Reinecke 		union myrs_cmd_mbox *mbox)
251777266186SHannes Reinecke {
251877266186SHannes Reinecke 	memcpy(&mem_mbox->words[1], &mbox->words[1],
251977266186SHannes Reinecke 	       sizeof(union myrs_cmd_mbox) - sizeof(unsigned int));
252077266186SHannes Reinecke 	/* Barrier to avoid reordering */
252177266186SHannes Reinecke 	wmb();
252277266186SHannes Reinecke 	mem_mbox->words[0] = mbox->words[0];
252377266186SHannes Reinecke 	/* Barrier to force PCI access */
252477266186SHannes Reinecke 	mb();
252577266186SHannes Reinecke }
252677266186SHannes Reinecke 
252777266186SHannes Reinecke static inline void DAC960_GEM_write_hw_mbox(void __iomem *base,
252877266186SHannes Reinecke 		dma_addr_t cmd_mbox_addr)
252977266186SHannes Reinecke {
253077266186SHannes Reinecke 	dma_addr_writeql(cmd_mbox_addr, base + DAC960_GEM_CMDMBX_OFFSET);
253177266186SHannes Reinecke }
253277266186SHannes Reinecke 
253377266186SHannes Reinecke static inline unsigned short DAC960_GEM_read_cmd_ident(void __iomem *base)
253477266186SHannes Reinecke {
253577266186SHannes Reinecke 	return readw(base + DAC960_GEM_CMDSTS_OFFSET);
253677266186SHannes Reinecke }
253777266186SHannes Reinecke 
253877266186SHannes Reinecke static inline unsigned char DAC960_GEM_read_cmd_status(void __iomem *base)
253977266186SHannes Reinecke {
254077266186SHannes Reinecke 	return readw(base + DAC960_GEM_CMDSTS_OFFSET + 2);
254177266186SHannes Reinecke }
254277266186SHannes Reinecke 
254377266186SHannes Reinecke static inline bool
254477266186SHannes Reinecke DAC960_GEM_read_error_status(void __iomem *base, unsigned char *error,
254577266186SHannes Reinecke 		unsigned char *param0, unsigned char *param1)
254677266186SHannes Reinecke {
254777266186SHannes Reinecke 	__le32 val;
254877266186SHannes Reinecke 
254977266186SHannes Reinecke 	val = readl(base + DAC960_GEM_ERRSTS_READ_OFFSET);
255077266186SHannes Reinecke 	if (!((le32_to_cpu(val) >> 24) & DAC960_GEM_ERRSTS_PENDING))
255177266186SHannes Reinecke 		return false;
255277266186SHannes Reinecke 	*error = val & ~(DAC960_GEM_ERRSTS_PENDING << 24);
255377266186SHannes Reinecke 	*param0 = readb(base + DAC960_GEM_CMDMBX_OFFSET + 0);
255477266186SHannes Reinecke 	*param1 = readb(base + DAC960_GEM_CMDMBX_OFFSET + 1);
255577266186SHannes Reinecke 	writel(0x03000000, base + DAC960_GEM_ERRSTS_CLEAR_OFFSET);
255677266186SHannes Reinecke 	return true;
255777266186SHannes Reinecke }
255877266186SHannes Reinecke 
255977266186SHannes Reinecke static inline unsigned char
256077266186SHannes Reinecke DAC960_GEM_mbox_init(void __iomem *base, dma_addr_t mbox_addr)
256177266186SHannes Reinecke {
256277266186SHannes Reinecke 	unsigned char status;
256377266186SHannes Reinecke 
256477266186SHannes Reinecke 	while (DAC960_GEM_hw_mbox_is_full(base))
256577266186SHannes Reinecke 		udelay(1);
256677266186SHannes Reinecke 	DAC960_GEM_write_hw_mbox(base, mbox_addr);
256777266186SHannes Reinecke 	DAC960_GEM_hw_mbox_new_cmd(base);
256877266186SHannes Reinecke 	while (!DAC960_GEM_hw_mbox_status_available(base))
256977266186SHannes Reinecke 		udelay(1);
257077266186SHannes Reinecke 	status = DAC960_GEM_read_cmd_status(base);
257177266186SHannes Reinecke 	DAC960_GEM_ack_hw_mbox_intr(base);
257277266186SHannes Reinecke 	DAC960_GEM_ack_hw_mbox_status(base);
257377266186SHannes Reinecke 
257477266186SHannes Reinecke 	return status;
257577266186SHannes Reinecke }
257677266186SHannes Reinecke 
257777266186SHannes Reinecke static int DAC960_GEM_hw_init(struct pci_dev *pdev,
257877266186SHannes Reinecke 		struct myrs_hba *cs, void __iomem *base)
257977266186SHannes Reinecke {
258077266186SHannes Reinecke 	int timeout = 0;
258177266186SHannes Reinecke 	unsigned char status, parm0, parm1;
258277266186SHannes Reinecke 
258377266186SHannes Reinecke 	DAC960_GEM_disable_intr(base);
258477266186SHannes Reinecke 	DAC960_GEM_ack_hw_mbox_status(base);
258577266186SHannes Reinecke 	udelay(1000);
258677266186SHannes Reinecke 	while (DAC960_GEM_init_in_progress(base) &&
258777266186SHannes Reinecke 	       timeout < MYRS_MAILBOX_TIMEOUT) {
258877266186SHannes Reinecke 		if (DAC960_GEM_read_error_status(base, &status,
258977266186SHannes Reinecke 						 &parm0, &parm1) &&
259077266186SHannes Reinecke 		    myrs_err_status(cs, status, parm0, parm1))
259177266186SHannes Reinecke 			return -EIO;
259277266186SHannes Reinecke 		udelay(10);
259377266186SHannes Reinecke 		timeout++;
259477266186SHannes Reinecke 	}
259577266186SHannes Reinecke 	if (timeout == MYRS_MAILBOX_TIMEOUT) {
259677266186SHannes Reinecke 		dev_err(&pdev->dev,
259777266186SHannes Reinecke 			"Timeout waiting for Controller Initialisation\n");
259877266186SHannes Reinecke 		return -ETIMEDOUT;
259977266186SHannes Reinecke 	}
260077266186SHannes Reinecke 	if (!myrs_enable_mmio_mbox(cs, DAC960_GEM_mbox_init)) {
260177266186SHannes Reinecke 		dev_err(&pdev->dev,
260277266186SHannes Reinecke 			"Unable to Enable Memory Mailbox Interface\n");
260377266186SHannes Reinecke 		DAC960_GEM_reset_ctrl(base);
260477266186SHannes Reinecke 		return -EAGAIN;
260577266186SHannes Reinecke 	}
260677266186SHannes Reinecke 	DAC960_GEM_enable_intr(base);
260777266186SHannes Reinecke 	cs->write_cmd_mbox = DAC960_GEM_write_cmd_mbox;
260877266186SHannes Reinecke 	cs->get_cmd_mbox = DAC960_GEM_mem_mbox_new_cmd;
260977266186SHannes Reinecke 	cs->disable_intr = DAC960_GEM_disable_intr;
261077266186SHannes Reinecke 	cs->reset = DAC960_GEM_reset_ctrl;
261177266186SHannes Reinecke 	return 0;
261277266186SHannes Reinecke }
261377266186SHannes Reinecke 
261477266186SHannes Reinecke static irqreturn_t DAC960_GEM_intr_handler(int irq, void *arg)
261577266186SHannes Reinecke {
261677266186SHannes Reinecke 	struct myrs_hba *cs = arg;
261777266186SHannes Reinecke 	void __iomem *base = cs->io_base;
261877266186SHannes Reinecke 	struct myrs_stat_mbox *next_stat_mbox;
261977266186SHannes Reinecke 	unsigned long flags;
262077266186SHannes Reinecke 
262177266186SHannes Reinecke 	spin_lock_irqsave(&cs->queue_lock, flags);
262277266186SHannes Reinecke 	DAC960_GEM_ack_intr(base);
262377266186SHannes Reinecke 	next_stat_mbox = cs->next_stat_mbox;
262477266186SHannes Reinecke 	while (next_stat_mbox->id > 0) {
262577266186SHannes Reinecke 		unsigned short id = next_stat_mbox->id;
262677266186SHannes Reinecke 		struct scsi_cmnd *scmd = NULL;
262777266186SHannes Reinecke 		struct myrs_cmdblk *cmd_blk = NULL;
262877266186SHannes Reinecke 
262977266186SHannes Reinecke 		if (id == MYRS_DCMD_TAG)
263077266186SHannes Reinecke 			cmd_blk = &cs->dcmd_blk;
263177266186SHannes Reinecke 		else if (id == MYRS_MCMD_TAG)
263277266186SHannes Reinecke 			cmd_blk = &cs->mcmd_blk;
263377266186SHannes Reinecke 		else {
263477266186SHannes Reinecke 			scmd = scsi_host_find_tag(cs->host, id - 3);
263577266186SHannes Reinecke 			if (scmd)
263677266186SHannes Reinecke 				cmd_blk = scsi_cmd_priv(scmd);
263777266186SHannes Reinecke 		}
263877266186SHannes Reinecke 		if (cmd_blk) {
263977266186SHannes Reinecke 			cmd_blk->status = next_stat_mbox->status;
264077266186SHannes Reinecke 			cmd_blk->sense_len = next_stat_mbox->sense_len;
264177266186SHannes Reinecke 			cmd_blk->residual = next_stat_mbox->residual;
264277266186SHannes Reinecke 		} else
264377266186SHannes Reinecke 			dev_err(&cs->pdev->dev,
264477266186SHannes Reinecke 				"Unhandled command completion %d\n", id);
264577266186SHannes Reinecke 
264677266186SHannes Reinecke 		memset(next_stat_mbox, 0, sizeof(struct myrs_stat_mbox));
264777266186SHannes Reinecke 		if (++next_stat_mbox > cs->last_stat_mbox)
264877266186SHannes Reinecke 			next_stat_mbox = cs->first_stat_mbox;
264977266186SHannes Reinecke 
265077266186SHannes Reinecke 		if (cmd_blk) {
265177266186SHannes Reinecke 			if (id < 3)
265277266186SHannes Reinecke 				myrs_handle_cmdblk(cs, cmd_blk);
265377266186SHannes Reinecke 			else
265477266186SHannes Reinecke 				myrs_handle_scsi(cs, cmd_blk, scmd);
265577266186SHannes Reinecke 		}
265677266186SHannes Reinecke 	}
265777266186SHannes Reinecke 	cs->next_stat_mbox = next_stat_mbox;
265877266186SHannes Reinecke 	spin_unlock_irqrestore(&cs->queue_lock, flags);
265977266186SHannes Reinecke 	return IRQ_HANDLED;
266077266186SHannes Reinecke }
266177266186SHannes Reinecke 
266277266186SHannes Reinecke struct myrs_privdata DAC960_GEM_privdata = {
266377266186SHannes Reinecke 	.hw_init =		DAC960_GEM_hw_init,
266477266186SHannes Reinecke 	.irq_handler =		DAC960_GEM_intr_handler,
266577266186SHannes Reinecke 	.mmio_size =		DAC960_GEM_mmio_size,
266677266186SHannes Reinecke };
266777266186SHannes Reinecke 
266877266186SHannes Reinecke /*
266977266186SHannes Reinecke  * DAC960 BA Series Controllers.
267077266186SHannes Reinecke  */
267177266186SHannes Reinecke 
267277266186SHannes Reinecke static inline void DAC960_BA_hw_mbox_new_cmd(void __iomem *base)
267377266186SHannes Reinecke {
267477266186SHannes Reinecke 	writeb(DAC960_BA_IDB_HWMBOX_NEW_CMD, base + DAC960_BA_IDB_OFFSET);
267577266186SHannes Reinecke }
267677266186SHannes Reinecke 
267777266186SHannes Reinecke static inline void DAC960_BA_ack_hw_mbox_status(void __iomem *base)
267877266186SHannes Reinecke {
267977266186SHannes Reinecke 	writeb(DAC960_BA_IDB_HWMBOX_ACK_STS, base + DAC960_BA_IDB_OFFSET);
268077266186SHannes Reinecke }
268177266186SHannes Reinecke 
268277266186SHannes Reinecke static inline void DAC960_BA_gen_intr(void __iomem *base)
268377266186SHannes Reinecke {
268477266186SHannes Reinecke 	writeb(DAC960_BA_IDB_GEN_IRQ, base + DAC960_BA_IDB_OFFSET);
268577266186SHannes Reinecke }
268677266186SHannes Reinecke 
268777266186SHannes Reinecke static inline void DAC960_BA_reset_ctrl(void __iomem *base)
268877266186SHannes Reinecke {
268977266186SHannes Reinecke 	writeb(DAC960_BA_IDB_CTRL_RESET, base + DAC960_BA_IDB_OFFSET);
269077266186SHannes Reinecke }
269177266186SHannes Reinecke 
269277266186SHannes Reinecke static inline void DAC960_BA_mem_mbox_new_cmd(void __iomem *base)
269377266186SHannes Reinecke {
269477266186SHannes Reinecke 	writeb(DAC960_BA_IDB_MMBOX_NEW_CMD, base + DAC960_BA_IDB_OFFSET);
269577266186SHannes Reinecke }
269677266186SHannes Reinecke 
269777266186SHannes Reinecke static inline bool DAC960_BA_hw_mbox_is_full(void __iomem *base)
269877266186SHannes Reinecke {
269977266186SHannes Reinecke 	u8 val;
270077266186SHannes Reinecke 
270177266186SHannes Reinecke 	val = readb(base + DAC960_BA_IDB_OFFSET);
270277266186SHannes Reinecke 	return !(val & DAC960_BA_IDB_HWMBOX_EMPTY);
270377266186SHannes Reinecke }
270477266186SHannes Reinecke 
270577266186SHannes Reinecke static inline bool DAC960_BA_init_in_progress(void __iomem *base)
270677266186SHannes Reinecke {
270777266186SHannes Reinecke 	u8 val;
270877266186SHannes Reinecke 
270977266186SHannes Reinecke 	val = readb(base + DAC960_BA_IDB_OFFSET);
271077266186SHannes Reinecke 	return !(val & DAC960_BA_IDB_INIT_DONE);
271177266186SHannes Reinecke }
271277266186SHannes Reinecke 
271377266186SHannes Reinecke static inline void DAC960_BA_ack_hw_mbox_intr(void __iomem *base)
271477266186SHannes Reinecke {
271577266186SHannes Reinecke 	writeb(DAC960_BA_ODB_HWMBOX_ACK_IRQ, base + DAC960_BA_ODB_OFFSET);
271677266186SHannes Reinecke }
271777266186SHannes Reinecke 
271877266186SHannes Reinecke static inline void DAC960_BA_ack_mem_mbox_intr(void __iomem *base)
271977266186SHannes Reinecke {
272077266186SHannes Reinecke 	writeb(DAC960_BA_ODB_MMBOX_ACK_IRQ, base + DAC960_BA_ODB_OFFSET);
272177266186SHannes Reinecke }
272277266186SHannes Reinecke 
272377266186SHannes Reinecke static inline void DAC960_BA_ack_intr(void __iomem *base)
272477266186SHannes Reinecke {
272577266186SHannes Reinecke 	writeb(DAC960_BA_ODB_HWMBOX_ACK_IRQ | DAC960_BA_ODB_MMBOX_ACK_IRQ,
272677266186SHannes Reinecke 	       base + DAC960_BA_ODB_OFFSET);
272777266186SHannes Reinecke }
272877266186SHannes Reinecke 
272977266186SHannes Reinecke static inline bool DAC960_BA_hw_mbox_status_available(void __iomem *base)
273077266186SHannes Reinecke {
273177266186SHannes Reinecke 	u8 val;
273277266186SHannes Reinecke 
273377266186SHannes Reinecke 	val = readb(base + DAC960_BA_ODB_OFFSET);
273477266186SHannes Reinecke 	return val & DAC960_BA_ODB_HWMBOX_STS_AVAIL;
273577266186SHannes Reinecke }
273677266186SHannes Reinecke 
273777266186SHannes Reinecke static inline bool DAC960_BA_mem_mbox_status_available(void __iomem *base)
273877266186SHannes Reinecke {
273977266186SHannes Reinecke 	u8 val;
274077266186SHannes Reinecke 
274177266186SHannes Reinecke 	val = readb(base + DAC960_BA_ODB_OFFSET);
274277266186SHannes Reinecke 	return val & DAC960_BA_ODB_MMBOX_STS_AVAIL;
274377266186SHannes Reinecke }
274477266186SHannes Reinecke 
274577266186SHannes Reinecke static inline void DAC960_BA_enable_intr(void __iomem *base)
274677266186SHannes Reinecke {
274777266186SHannes Reinecke 	writeb(~DAC960_BA_IRQMASK_DISABLE_IRQ, base + DAC960_BA_IRQMASK_OFFSET);
274877266186SHannes Reinecke }
274977266186SHannes Reinecke 
275077266186SHannes Reinecke static inline void DAC960_BA_disable_intr(void __iomem *base)
275177266186SHannes Reinecke {
275277266186SHannes Reinecke 	writeb(0xFF, base + DAC960_BA_IRQMASK_OFFSET);
275377266186SHannes Reinecke }
275477266186SHannes Reinecke 
275577266186SHannes Reinecke static inline bool DAC960_BA_intr_enabled(void __iomem *base)
275677266186SHannes Reinecke {
275777266186SHannes Reinecke 	u8 val;
275877266186SHannes Reinecke 
275977266186SHannes Reinecke 	val = readb(base + DAC960_BA_IRQMASK_OFFSET);
276077266186SHannes Reinecke 	return !(val & DAC960_BA_IRQMASK_DISABLE_IRQ);
276177266186SHannes Reinecke }
276277266186SHannes Reinecke 
276377266186SHannes Reinecke static inline void DAC960_BA_write_cmd_mbox(union myrs_cmd_mbox *mem_mbox,
276477266186SHannes Reinecke 		union myrs_cmd_mbox *mbox)
276577266186SHannes Reinecke {
276677266186SHannes Reinecke 	memcpy(&mem_mbox->words[1], &mbox->words[1],
276777266186SHannes Reinecke 	       sizeof(union myrs_cmd_mbox) - sizeof(unsigned int));
276877266186SHannes Reinecke 	/* Barrier to avoid reordering */
276977266186SHannes Reinecke 	wmb();
277077266186SHannes Reinecke 	mem_mbox->words[0] = mbox->words[0];
277177266186SHannes Reinecke 	/* Barrier to force PCI access */
277277266186SHannes Reinecke 	mb();
277377266186SHannes Reinecke }
277477266186SHannes Reinecke 
277577266186SHannes Reinecke 
277677266186SHannes Reinecke static inline void DAC960_BA_write_hw_mbox(void __iomem *base,
277777266186SHannes Reinecke 		dma_addr_t cmd_mbox_addr)
277877266186SHannes Reinecke {
277977266186SHannes Reinecke 	dma_addr_writeql(cmd_mbox_addr, base + DAC960_BA_CMDMBX_OFFSET);
278077266186SHannes Reinecke }
278177266186SHannes Reinecke 
278277266186SHannes Reinecke static inline unsigned short DAC960_BA_read_cmd_ident(void __iomem *base)
278377266186SHannes Reinecke {
278477266186SHannes Reinecke 	return readw(base + DAC960_BA_CMDSTS_OFFSET);
278577266186SHannes Reinecke }
278677266186SHannes Reinecke 
278777266186SHannes Reinecke static inline unsigned char DAC960_BA_read_cmd_status(void __iomem *base)
278877266186SHannes Reinecke {
278977266186SHannes Reinecke 	return readw(base + DAC960_BA_CMDSTS_OFFSET + 2);
279077266186SHannes Reinecke }
279177266186SHannes Reinecke 
279277266186SHannes Reinecke static inline bool
279377266186SHannes Reinecke DAC960_BA_read_error_status(void __iomem *base, unsigned char *error,
279477266186SHannes Reinecke 		unsigned char *param0, unsigned char *param1)
279577266186SHannes Reinecke {
279677266186SHannes Reinecke 	u8 val;
279777266186SHannes Reinecke 
279877266186SHannes Reinecke 	val = readb(base + DAC960_BA_ERRSTS_OFFSET);
279977266186SHannes Reinecke 	if (!(val & DAC960_BA_ERRSTS_PENDING))
280077266186SHannes Reinecke 		return false;
280177266186SHannes Reinecke 	val &= ~DAC960_BA_ERRSTS_PENDING;
280277266186SHannes Reinecke 	*error = val;
280377266186SHannes Reinecke 	*param0 = readb(base + DAC960_BA_CMDMBX_OFFSET + 0);
280477266186SHannes Reinecke 	*param1 = readb(base + DAC960_BA_CMDMBX_OFFSET + 1);
280577266186SHannes Reinecke 	writeb(0xFF, base + DAC960_BA_ERRSTS_OFFSET);
280677266186SHannes Reinecke 	return true;
280777266186SHannes Reinecke }
280877266186SHannes Reinecke 
280977266186SHannes Reinecke static inline unsigned char
281077266186SHannes Reinecke DAC960_BA_mbox_init(void __iomem *base, dma_addr_t mbox_addr)
281177266186SHannes Reinecke {
281277266186SHannes Reinecke 	unsigned char status;
281377266186SHannes Reinecke 
281477266186SHannes Reinecke 	while (DAC960_BA_hw_mbox_is_full(base))
281577266186SHannes Reinecke 		udelay(1);
281677266186SHannes Reinecke 	DAC960_BA_write_hw_mbox(base, mbox_addr);
281777266186SHannes Reinecke 	DAC960_BA_hw_mbox_new_cmd(base);
281877266186SHannes Reinecke 	while (!DAC960_BA_hw_mbox_status_available(base))
281977266186SHannes Reinecke 		udelay(1);
282077266186SHannes Reinecke 	status = DAC960_BA_read_cmd_status(base);
282177266186SHannes Reinecke 	DAC960_BA_ack_hw_mbox_intr(base);
282277266186SHannes Reinecke 	DAC960_BA_ack_hw_mbox_status(base);
282377266186SHannes Reinecke 
282477266186SHannes Reinecke 	return status;
282577266186SHannes Reinecke }
282677266186SHannes Reinecke 
282777266186SHannes Reinecke static int DAC960_BA_hw_init(struct pci_dev *pdev,
282877266186SHannes Reinecke 		struct myrs_hba *cs, void __iomem *base)
282977266186SHannes Reinecke {
283077266186SHannes Reinecke 	int timeout = 0;
283177266186SHannes Reinecke 	unsigned char status, parm0, parm1;
283277266186SHannes Reinecke 
283377266186SHannes Reinecke 	DAC960_BA_disable_intr(base);
283477266186SHannes Reinecke 	DAC960_BA_ack_hw_mbox_status(base);
283577266186SHannes Reinecke 	udelay(1000);
283677266186SHannes Reinecke 	while (DAC960_BA_init_in_progress(base) &&
283777266186SHannes Reinecke 	       timeout < MYRS_MAILBOX_TIMEOUT) {
283877266186SHannes Reinecke 		if (DAC960_BA_read_error_status(base, &status,
283977266186SHannes Reinecke 					      &parm0, &parm1) &&
284077266186SHannes Reinecke 		    myrs_err_status(cs, status, parm0, parm1))
284177266186SHannes Reinecke 			return -EIO;
284277266186SHannes Reinecke 		udelay(10);
284377266186SHannes Reinecke 		timeout++;
284477266186SHannes Reinecke 	}
284577266186SHannes Reinecke 	if (timeout == MYRS_MAILBOX_TIMEOUT) {
284677266186SHannes Reinecke 		dev_err(&pdev->dev,
284777266186SHannes Reinecke 			"Timeout waiting for Controller Initialisation\n");
284877266186SHannes Reinecke 		return -ETIMEDOUT;
284977266186SHannes Reinecke 	}
285077266186SHannes Reinecke 	if (!myrs_enable_mmio_mbox(cs, DAC960_BA_mbox_init)) {
285177266186SHannes Reinecke 		dev_err(&pdev->dev,
285277266186SHannes Reinecke 			"Unable to Enable Memory Mailbox Interface\n");
285377266186SHannes Reinecke 		DAC960_BA_reset_ctrl(base);
285477266186SHannes Reinecke 		return -EAGAIN;
285577266186SHannes Reinecke 	}
285677266186SHannes Reinecke 	DAC960_BA_enable_intr(base);
285777266186SHannes Reinecke 	cs->write_cmd_mbox = DAC960_BA_write_cmd_mbox;
285877266186SHannes Reinecke 	cs->get_cmd_mbox = DAC960_BA_mem_mbox_new_cmd;
285977266186SHannes Reinecke 	cs->disable_intr = DAC960_BA_disable_intr;
286077266186SHannes Reinecke 	cs->reset = DAC960_BA_reset_ctrl;
286177266186SHannes Reinecke 	return 0;
286277266186SHannes Reinecke }
286377266186SHannes Reinecke 
286477266186SHannes Reinecke static irqreturn_t DAC960_BA_intr_handler(int irq, void *arg)
286577266186SHannes Reinecke {
286677266186SHannes Reinecke 	struct myrs_hba *cs = arg;
286777266186SHannes Reinecke 	void __iomem *base = cs->io_base;
286877266186SHannes Reinecke 	struct myrs_stat_mbox *next_stat_mbox;
286977266186SHannes Reinecke 	unsigned long flags;
287077266186SHannes Reinecke 
287177266186SHannes Reinecke 	spin_lock_irqsave(&cs->queue_lock, flags);
287277266186SHannes Reinecke 	DAC960_BA_ack_intr(base);
287377266186SHannes Reinecke 	next_stat_mbox = cs->next_stat_mbox;
287477266186SHannes Reinecke 	while (next_stat_mbox->id > 0) {
287577266186SHannes Reinecke 		unsigned short id = next_stat_mbox->id;
287677266186SHannes Reinecke 		struct scsi_cmnd *scmd = NULL;
287777266186SHannes Reinecke 		struct myrs_cmdblk *cmd_blk = NULL;
287877266186SHannes Reinecke 
287977266186SHannes Reinecke 		if (id == MYRS_DCMD_TAG)
288077266186SHannes Reinecke 			cmd_blk = &cs->dcmd_blk;
288177266186SHannes Reinecke 		else if (id == MYRS_MCMD_TAG)
288277266186SHannes Reinecke 			cmd_blk = &cs->mcmd_blk;
288377266186SHannes Reinecke 		else {
288477266186SHannes Reinecke 			scmd = scsi_host_find_tag(cs->host, id - 3);
288577266186SHannes Reinecke 			if (scmd)
288677266186SHannes Reinecke 				cmd_blk = scsi_cmd_priv(scmd);
288777266186SHannes Reinecke 		}
288877266186SHannes Reinecke 		if (cmd_blk) {
288977266186SHannes Reinecke 			cmd_blk->status = next_stat_mbox->status;
289077266186SHannes Reinecke 			cmd_blk->sense_len = next_stat_mbox->sense_len;
289177266186SHannes Reinecke 			cmd_blk->residual = next_stat_mbox->residual;
289277266186SHannes Reinecke 		} else
289377266186SHannes Reinecke 			dev_err(&cs->pdev->dev,
289477266186SHannes Reinecke 				"Unhandled command completion %d\n", id);
289577266186SHannes Reinecke 
289677266186SHannes Reinecke 		memset(next_stat_mbox, 0, sizeof(struct myrs_stat_mbox));
289777266186SHannes Reinecke 		if (++next_stat_mbox > cs->last_stat_mbox)
289877266186SHannes Reinecke 			next_stat_mbox = cs->first_stat_mbox;
289977266186SHannes Reinecke 
290077266186SHannes Reinecke 		if (cmd_blk) {
290177266186SHannes Reinecke 			if (id < 3)
290277266186SHannes Reinecke 				myrs_handle_cmdblk(cs, cmd_blk);
290377266186SHannes Reinecke 			else
290477266186SHannes Reinecke 				myrs_handle_scsi(cs, cmd_blk, scmd);
290577266186SHannes Reinecke 		}
290677266186SHannes Reinecke 	}
290777266186SHannes Reinecke 	cs->next_stat_mbox = next_stat_mbox;
290877266186SHannes Reinecke 	spin_unlock_irqrestore(&cs->queue_lock, flags);
290977266186SHannes Reinecke 	return IRQ_HANDLED;
291077266186SHannes Reinecke }
291177266186SHannes Reinecke 
291277266186SHannes Reinecke struct myrs_privdata DAC960_BA_privdata = {
291377266186SHannes Reinecke 	.hw_init =		DAC960_BA_hw_init,
291477266186SHannes Reinecke 	.irq_handler =		DAC960_BA_intr_handler,
291577266186SHannes Reinecke 	.mmio_size =		DAC960_BA_mmio_size,
291677266186SHannes Reinecke };
291777266186SHannes Reinecke 
291877266186SHannes Reinecke /*
291977266186SHannes Reinecke  * DAC960 LP Series Controllers.
292077266186SHannes Reinecke  */
292177266186SHannes Reinecke 
292277266186SHannes Reinecke static inline void DAC960_LP_hw_mbox_new_cmd(void __iomem *base)
292377266186SHannes Reinecke {
292477266186SHannes Reinecke 	writeb(DAC960_LP_IDB_HWMBOX_NEW_CMD, base + DAC960_LP_IDB_OFFSET);
292577266186SHannes Reinecke }
292677266186SHannes Reinecke 
292777266186SHannes Reinecke static inline void DAC960_LP_ack_hw_mbox_status(void __iomem *base)
292877266186SHannes Reinecke {
292977266186SHannes Reinecke 	writeb(DAC960_LP_IDB_HWMBOX_ACK_STS, base + DAC960_LP_IDB_OFFSET);
293077266186SHannes Reinecke }
293177266186SHannes Reinecke 
293277266186SHannes Reinecke static inline void DAC960_LP_gen_intr(void __iomem *base)
293377266186SHannes Reinecke {
293477266186SHannes Reinecke 	writeb(DAC960_LP_IDB_GEN_IRQ, base + DAC960_LP_IDB_OFFSET);
293577266186SHannes Reinecke }
293677266186SHannes Reinecke 
293777266186SHannes Reinecke static inline void DAC960_LP_reset_ctrl(void __iomem *base)
293877266186SHannes Reinecke {
293977266186SHannes Reinecke 	writeb(DAC960_LP_IDB_CTRL_RESET, base + DAC960_LP_IDB_OFFSET);
294077266186SHannes Reinecke }
294177266186SHannes Reinecke 
294277266186SHannes Reinecke static inline void DAC960_LP_mem_mbox_new_cmd(void __iomem *base)
294377266186SHannes Reinecke {
294477266186SHannes Reinecke 	writeb(DAC960_LP_IDB_MMBOX_NEW_CMD, base + DAC960_LP_IDB_OFFSET);
294577266186SHannes Reinecke }
294677266186SHannes Reinecke 
294777266186SHannes Reinecke static inline bool DAC960_LP_hw_mbox_is_full(void __iomem *base)
294877266186SHannes Reinecke {
294977266186SHannes Reinecke 	u8 val;
295077266186SHannes Reinecke 
295177266186SHannes Reinecke 	val = readb(base + DAC960_LP_IDB_OFFSET);
295277266186SHannes Reinecke 	return val & DAC960_LP_IDB_HWMBOX_FULL;
295377266186SHannes Reinecke }
295477266186SHannes Reinecke 
295577266186SHannes Reinecke static inline bool DAC960_LP_init_in_progress(void __iomem *base)
295677266186SHannes Reinecke {
295777266186SHannes Reinecke 	u8 val;
295877266186SHannes Reinecke 
295977266186SHannes Reinecke 	val = readb(base + DAC960_LP_IDB_OFFSET);
296077266186SHannes Reinecke 	return val & DAC960_LP_IDB_INIT_IN_PROGRESS;
296177266186SHannes Reinecke }
296277266186SHannes Reinecke 
296377266186SHannes Reinecke static inline void DAC960_LP_ack_hw_mbox_intr(void __iomem *base)
296477266186SHannes Reinecke {
296577266186SHannes Reinecke 	writeb(DAC960_LP_ODB_HWMBOX_ACK_IRQ, base + DAC960_LP_ODB_OFFSET);
296677266186SHannes Reinecke }
296777266186SHannes Reinecke 
296877266186SHannes Reinecke static inline void DAC960_LP_ack_mem_mbox_intr(void __iomem *base)
296977266186SHannes Reinecke {
297077266186SHannes Reinecke 	writeb(DAC960_LP_ODB_MMBOX_ACK_IRQ, base + DAC960_LP_ODB_OFFSET);
297177266186SHannes Reinecke }
297277266186SHannes Reinecke 
297377266186SHannes Reinecke static inline void DAC960_LP_ack_intr(void __iomem *base)
297477266186SHannes Reinecke {
297577266186SHannes Reinecke 	writeb(DAC960_LP_ODB_HWMBOX_ACK_IRQ | DAC960_LP_ODB_MMBOX_ACK_IRQ,
297677266186SHannes Reinecke 	       base + DAC960_LP_ODB_OFFSET);
297777266186SHannes Reinecke }
297877266186SHannes Reinecke 
297977266186SHannes Reinecke static inline bool DAC960_LP_hw_mbox_status_available(void __iomem *base)
298077266186SHannes Reinecke {
298177266186SHannes Reinecke 	u8 val;
298277266186SHannes Reinecke 
298377266186SHannes Reinecke 	val = readb(base + DAC960_LP_ODB_OFFSET);
298477266186SHannes Reinecke 	return val & DAC960_LP_ODB_HWMBOX_STS_AVAIL;
298577266186SHannes Reinecke }
298677266186SHannes Reinecke 
298777266186SHannes Reinecke static inline bool DAC960_LP_mem_mbox_status_available(void __iomem *base)
298877266186SHannes Reinecke {
298977266186SHannes Reinecke 	u8 val;
299077266186SHannes Reinecke 
299177266186SHannes Reinecke 	val = readb(base + DAC960_LP_ODB_OFFSET);
299277266186SHannes Reinecke 	return val & DAC960_LP_ODB_MMBOX_STS_AVAIL;
299377266186SHannes Reinecke }
299477266186SHannes Reinecke 
299577266186SHannes Reinecke static inline void DAC960_LP_enable_intr(void __iomem *base)
299677266186SHannes Reinecke {
299777266186SHannes Reinecke 	writeb(~DAC960_LP_IRQMASK_DISABLE_IRQ, base + DAC960_LP_IRQMASK_OFFSET);
299877266186SHannes Reinecke }
299977266186SHannes Reinecke 
300077266186SHannes Reinecke static inline void DAC960_LP_disable_intr(void __iomem *base)
300177266186SHannes Reinecke {
300277266186SHannes Reinecke 	writeb(0xFF, base + DAC960_LP_IRQMASK_OFFSET);
300377266186SHannes Reinecke }
300477266186SHannes Reinecke 
300577266186SHannes Reinecke static inline bool DAC960_LP_intr_enabled(void __iomem *base)
300677266186SHannes Reinecke {
300777266186SHannes Reinecke 	u8 val;
300877266186SHannes Reinecke 
300977266186SHannes Reinecke 	val = readb(base + DAC960_LP_IRQMASK_OFFSET);
301077266186SHannes Reinecke 	return !(val & DAC960_LP_IRQMASK_DISABLE_IRQ);
301177266186SHannes Reinecke }
301277266186SHannes Reinecke 
301377266186SHannes Reinecke static inline void DAC960_LP_write_cmd_mbox(union myrs_cmd_mbox *mem_mbox,
301477266186SHannes Reinecke 		union myrs_cmd_mbox *mbox)
301577266186SHannes Reinecke {
301677266186SHannes Reinecke 	memcpy(&mem_mbox->words[1], &mbox->words[1],
301777266186SHannes Reinecke 	       sizeof(union myrs_cmd_mbox) - sizeof(unsigned int));
301877266186SHannes Reinecke 	/* Barrier to avoid reordering */
301977266186SHannes Reinecke 	wmb();
302077266186SHannes Reinecke 	mem_mbox->words[0] = mbox->words[0];
302177266186SHannes Reinecke 	/* Barrier to force PCI access */
302277266186SHannes Reinecke 	mb();
302377266186SHannes Reinecke }
302477266186SHannes Reinecke 
302577266186SHannes Reinecke static inline void DAC960_LP_write_hw_mbox(void __iomem *base,
302677266186SHannes Reinecke 		dma_addr_t cmd_mbox_addr)
302777266186SHannes Reinecke {
302877266186SHannes Reinecke 	dma_addr_writeql(cmd_mbox_addr, base + DAC960_LP_CMDMBX_OFFSET);
302977266186SHannes Reinecke }
303077266186SHannes Reinecke 
303177266186SHannes Reinecke static inline unsigned short DAC960_LP_read_cmd_ident(void __iomem *base)
303277266186SHannes Reinecke {
303377266186SHannes Reinecke 	return readw(base + DAC960_LP_CMDSTS_OFFSET);
303477266186SHannes Reinecke }
303577266186SHannes Reinecke 
303677266186SHannes Reinecke static inline unsigned char DAC960_LP_read_cmd_status(void __iomem *base)
303777266186SHannes Reinecke {
303877266186SHannes Reinecke 	return readw(base + DAC960_LP_CMDSTS_OFFSET + 2);
303977266186SHannes Reinecke }
304077266186SHannes Reinecke 
304177266186SHannes Reinecke static inline bool
304277266186SHannes Reinecke DAC960_LP_read_error_status(void __iomem *base, unsigned char *error,
304377266186SHannes Reinecke 		unsigned char *param0, unsigned char *param1)
304477266186SHannes Reinecke {
304577266186SHannes Reinecke 	u8 val;
304677266186SHannes Reinecke 
304777266186SHannes Reinecke 	val = readb(base + DAC960_LP_ERRSTS_OFFSET);
304877266186SHannes Reinecke 	if (!(val & DAC960_LP_ERRSTS_PENDING))
304977266186SHannes Reinecke 		return false;
305077266186SHannes Reinecke 	val &= ~DAC960_LP_ERRSTS_PENDING;
305177266186SHannes Reinecke 	*error = val;
305277266186SHannes Reinecke 	*param0 = readb(base + DAC960_LP_CMDMBX_OFFSET + 0);
305377266186SHannes Reinecke 	*param1 = readb(base + DAC960_LP_CMDMBX_OFFSET + 1);
305477266186SHannes Reinecke 	writeb(0xFF, base + DAC960_LP_ERRSTS_OFFSET);
305577266186SHannes Reinecke 	return true;
305677266186SHannes Reinecke }
305777266186SHannes Reinecke 
305877266186SHannes Reinecke static inline unsigned char
305977266186SHannes Reinecke DAC960_LP_mbox_init(void __iomem *base, dma_addr_t mbox_addr)
306077266186SHannes Reinecke {
306177266186SHannes Reinecke 	unsigned char status;
306277266186SHannes Reinecke 
306377266186SHannes Reinecke 	while (DAC960_LP_hw_mbox_is_full(base))
306477266186SHannes Reinecke 		udelay(1);
306577266186SHannes Reinecke 	DAC960_LP_write_hw_mbox(base, mbox_addr);
306677266186SHannes Reinecke 	DAC960_LP_hw_mbox_new_cmd(base);
306777266186SHannes Reinecke 	while (!DAC960_LP_hw_mbox_status_available(base))
306877266186SHannes Reinecke 		udelay(1);
306977266186SHannes Reinecke 	status = DAC960_LP_read_cmd_status(base);
307077266186SHannes Reinecke 	DAC960_LP_ack_hw_mbox_intr(base);
307177266186SHannes Reinecke 	DAC960_LP_ack_hw_mbox_status(base);
307277266186SHannes Reinecke 
307377266186SHannes Reinecke 	return status;
307477266186SHannes Reinecke }
307577266186SHannes Reinecke 
307677266186SHannes Reinecke static int DAC960_LP_hw_init(struct pci_dev *pdev,
307777266186SHannes Reinecke 		struct myrs_hba *cs, void __iomem *base)
307877266186SHannes Reinecke {
307977266186SHannes Reinecke 	int timeout = 0;
308077266186SHannes Reinecke 	unsigned char status, parm0, parm1;
308177266186SHannes Reinecke 
308277266186SHannes Reinecke 	DAC960_LP_disable_intr(base);
308377266186SHannes Reinecke 	DAC960_LP_ack_hw_mbox_status(base);
308477266186SHannes Reinecke 	udelay(1000);
308577266186SHannes Reinecke 	while (DAC960_LP_init_in_progress(base) &&
308677266186SHannes Reinecke 	       timeout < MYRS_MAILBOX_TIMEOUT) {
308777266186SHannes Reinecke 		if (DAC960_LP_read_error_status(base, &status,
308877266186SHannes Reinecke 					      &parm0, &parm1) &&
308977266186SHannes Reinecke 		    myrs_err_status(cs, status, parm0, parm1))
309077266186SHannes Reinecke 			return -EIO;
309177266186SHannes Reinecke 		udelay(10);
309277266186SHannes Reinecke 		timeout++;
309377266186SHannes Reinecke 	}
309477266186SHannes Reinecke 	if (timeout == MYRS_MAILBOX_TIMEOUT) {
309577266186SHannes Reinecke 		dev_err(&pdev->dev,
309677266186SHannes Reinecke 			"Timeout waiting for Controller Initialisation\n");
309777266186SHannes Reinecke 		return -ETIMEDOUT;
309877266186SHannes Reinecke 	}
309977266186SHannes Reinecke 	if (!myrs_enable_mmio_mbox(cs, DAC960_LP_mbox_init)) {
310077266186SHannes Reinecke 		dev_err(&pdev->dev,
310177266186SHannes Reinecke 			"Unable to Enable Memory Mailbox Interface\n");
310277266186SHannes Reinecke 		DAC960_LP_reset_ctrl(base);
310377266186SHannes Reinecke 		return -ENODEV;
310477266186SHannes Reinecke 	}
310577266186SHannes Reinecke 	DAC960_LP_enable_intr(base);
310677266186SHannes Reinecke 	cs->write_cmd_mbox = DAC960_LP_write_cmd_mbox;
310777266186SHannes Reinecke 	cs->get_cmd_mbox = DAC960_LP_mem_mbox_new_cmd;
310877266186SHannes Reinecke 	cs->disable_intr = DAC960_LP_disable_intr;
310977266186SHannes Reinecke 	cs->reset = DAC960_LP_reset_ctrl;
311077266186SHannes Reinecke 
311177266186SHannes Reinecke 	return 0;
311277266186SHannes Reinecke }
311377266186SHannes Reinecke 
311477266186SHannes Reinecke static irqreturn_t DAC960_LP_intr_handler(int irq, void *arg)
311577266186SHannes Reinecke {
311677266186SHannes Reinecke 	struct myrs_hba *cs = arg;
311777266186SHannes Reinecke 	void __iomem *base = cs->io_base;
311877266186SHannes Reinecke 	struct myrs_stat_mbox *next_stat_mbox;
311977266186SHannes Reinecke 	unsigned long flags;
312077266186SHannes Reinecke 
312177266186SHannes Reinecke 	spin_lock_irqsave(&cs->queue_lock, flags);
312277266186SHannes Reinecke 	DAC960_LP_ack_intr(base);
312377266186SHannes Reinecke 	next_stat_mbox = cs->next_stat_mbox;
312477266186SHannes Reinecke 	while (next_stat_mbox->id > 0) {
312577266186SHannes Reinecke 		unsigned short id = next_stat_mbox->id;
312677266186SHannes Reinecke 		struct scsi_cmnd *scmd = NULL;
312777266186SHannes Reinecke 		struct myrs_cmdblk *cmd_blk = NULL;
312877266186SHannes Reinecke 
312977266186SHannes Reinecke 		if (id == MYRS_DCMD_TAG)
313077266186SHannes Reinecke 			cmd_blk = &cs->dcmd_blk;
313177266186SHannes Reinecke 		else if (id == MYRS_MCMD_TAG)
313277266186SHannes Reinecke 			cmd_blk = &cs->mcmd_blk;
313377266186SHannes Reinecke 		else {
313477266186SHannes Reinecke 			scmd = scsi_host_find_tag(cs->host, id - 3);
313577266186SHannes Reinecke 			if (scmd)
313677266186SHannes Reinecke 				cmd_blk = scsi_cmd_priv(scmd);
313777266186SHannes Reinecke 		}
313877266186SHannes Reinecke 		if (cmd_blk) {
313977266186SHannes Reinecke 			cmd_blk->status = next_stat_mbox->status;
314077266186SHannes Reinecke 			cmd_blk->sense_len = next_stat_mbox->sense_len;
314177266186SHannes Reinecke 			cmd_blk->residual = next_stat_mbox->residual;
314277266186SHannes Reinecke 		} else
314377266186SHannes Reinecke 			dev_err(&cs->pdev->dev,
314477266186SHannes Reinecke 				"Unhandled command completion %d\n", id);
314577266186SHannes Reinecke 
314677266186SHannes Reinecke 		memset(next_stat_mbox, 0, sizeof(struct myrs_stat_mbox));
314777266186SHannes Reinecke 		if (++next_stat_mbox > cs->last_stat_mbox)
314877266186SHannes Reinecke 			next_stat_mbox = cs->first_stat_mbox;
314977266186SHannes Reinecke 
315077266186SHannes Reinecke 		if (cmd_blk) {
315177266186SHannes Reinecke 			if (id < 3)
315277266186SHannes Reinecke 				myrs_handle_cmdblk(cs, cmd_blk);
315377266186SHannes Reinecke 			else
315477266186SHannes Reinecke 				myrs_handle_scsi(cs, cmd_blk, scmd);
315577266186SHannes Reinecke 		}
315677266186SHannes Reinecke 	}
315777266186SHannes Reinecke 	cs->next_stat_mbox = next_stat_mbox;
315877266186SHannes Reinecke 	spin_unlock_irqrestore(&cs->queue_lock, flags);
315977266186SHannes Reinecke 	return IRQ_HANDLED;
316077266186SHannes Reinecke }
316177266186SHannes Reinecke 
316277266186SHannes Reinecke struct myrs_privdata DAC960_LP_privdata = {
316377266186SHannes Reinecke 	.hw_init =		DAC960_LP_hw_init,
316477266186SHannes Reinecke 	.irq_handler =		DAC960_LP_intr_handler,
316577266186SHannes Reinecke 	.mmio_size =		DAC960_LP_mmio_size,
316677266186SHannes Reinecke };
316777266186SHannes Reinecke 
316877266186SHannes Reinecke /*
316977266186SHannes Reinecke  * Module functions
317077266186SHannes Reinecke  */
317177266186SHannes Reinecke static int
317277266186SHannes Reinecke myrs_probe(struct pci_dev *dev, const struct pci_device_id *entry)
317377266186SHannes Reinecke {
317477266186SHannes Reinecke 	struct myrs_hba *cs;
317577266186SHannes Reinecke 	int ret;
317677266186SHannes Reinecke 
317777266186SHannes Reinecke 	cs = myrs_detect(dev, entry);
317877266186SHannes Reinecke 	if (!cs)
317977266186SHannes Reinecke 		return -ENODEV;
318077266186SHannes Reinecke 
318177266186SHannes Reinecke 	ret = myrs_get_config(cs);
318277266186SHannes Reinecke 	if (ret < 0) {
318377266186SHannes Reinecke 		myrs_cleanup(cs);
318477266186SHannes Reinecke 		return ret;
318577266186SHannes Reinecke 	}
318677266186SHannes Reinecke 
318777266186SHannes Reinecke 	if (!myrs_create_mempools(dev, cs)) {
318877266186SHannes Reinecke 		ret = -ENOMEM;
318977266186SHannes Reinecke 		goto failed;
319077266186SHannes Reinecke 	}
319177266186SHannes Reinecke 
319277266186SHannes Reinecke 	ret = scsi_add_host(cs->host, &dev->dev);
319377266186SHannes Reinecke 	if (ret) {
319477266186SHannes Reinecke 		dev_err(&dev->dev, "scsi_add_host failed with %d\n", ret);
319577266186SHannes Reinecke 		myrs_destroy_mempools(cs);
319677266186SHannes Reinecke 		goto failed;
319777266186SHannes Reinecke 	}
319877266186SHannes Reinecke 	scsi_scan_host(cs->host);
319977266186SHannes Reinecke 	return 0;
320077266186SHannes Reinecke failed:
320177266186SHannes Reinecke 	myrs_cleanup(cs);
320277266186SHannes Reinecke 	return ret;
320377266186SHannes Reinecke }
320477266186SHannes Reinecke 
320577266186SHannes Reinecke 
320677266186SHannes Reinecke static void myrs_remove(struct pci_dev *pdev)
320777266186SHannes Reinecke {
320877266186SHannes Reinecke 	struct myrs_hba *cs = pci_get_drvdata(pdev);
320977266186SHannes Reinecke 
321077266186SHannes Reinecke 	if (cs == NULL)
321177266186SHannes Reinecke 		return;
321277266186SHannes Reinecke 
321377266186SHannes Reinecke 	shost_printk(KERN_NOTICE, cs->host, "Flushing Cache...");
321477266186SHannes Reinecke 	myrs_flush_cache(cs);
321577266186SHannes Reinecke 	myrs_destroy_mempools(cs);
321677266186SHannes Reinecke 	myrs_cleanup(cs);
321777266186SHannes Reinecke }
321877266186SHannes Reinecke 
321977266186SHannes Reinecke 
322077266186SHannes Reinecke static const struct pci_device_id myrs_id_table[] = {
322177266186SHannes Reinecke 	{
322277266186SHannes Reinecke 		PCI_DEVICE_SUB(PCI_VENDOR_ID_MYLEX,
322377266186SHannes Reinecke 			       PCI_DEVICE_ID_MYLEX_DAC960_GEM,
322477266186SHannes Reinecke 			       PCI_VENDOR_ID_MYLEX, PCI_ANY_ID),
322577266186SHannes Reinecke 		.driver_data	= (unsigned long) &DAC960_GEM_privdata,
322677266186SHannes Reinecke 	},
322777266186SHannes Reinecke 	{
322877266186SHannes Reinecke 		PCI_DEVICE_DATA(MYLEX, DAC960_BA, &DAC960_BA_privdata),
322977266186SHannes Reinecke 	},
323077266186SHannes Reinecke 	{
323177266186SHannes Reinecke 		PCI_DEVICE_DATA(MYLEX, DAC960_LP, &DAC960_LP_privdata),
323277266186SHannes Reinecke 	},
323377266186SHannes Reinecke 	{0, },
323477266186SHannes Reinecke };
323577266186SHannes Reinecke 
323677266186SHannes Reinecke MODULE_DEVICE_TABLE(pci, myrs_id_table);
323777266186SHannes Reinecke 
323877266186SHannes Reinecke static struct pci_driver myrs_pci_driver = {
323977266186SHannes Reinecke 	.name		= "myrs",
324077266186SHannes Reinecke 	.id_table	= myrs_id_table,
324177266186SHannes Reinecke 	.probe		= myrs_probe,
324277266186SHannes Reinecke 	.remove		= myrs_remove,
324377266186SHannes Reinecke };
324477266186SHannes Reinecke 
324577266186SHannes Reinecke static int __init myrs_init_module(void)
324677266186SHannes Reinecke {
324777266186SHannes Reinecke 	int ret;
324877266186SHannes Reinecke 
324977266186SHannes Reinecke 	myrs_raid_template = raid_class_attach(&myrs_raid_functions);
325077266186SHannes Reinecke 	if (!myrs_raid_template)
325177266186SHannes Reinecke 		return -ENODEV;
325277266186SHannes Reinecke 
325377266186SHannes Reinecke 	ret = pci_register_driver(&myrs_pci_driver);
325477266186SHannes Reinecke 	if (ret)
325577266186SHannes Reinecke 		raid_class_release(myrs_raid_template);
325677266186SHannes Reinecke 
325777266186SHannes Reinecke 	return ret;
325877266186SHannes Reinecke }
325977266186SHannes Reinecke 
326077266186SHannes Reinecke static void __exit myrs_cleanup_module(void)
326177266186SHannes Reinecke {
326277266186SHannes Reinecke 	pci_unregister_driver(&myrs_pci_driver);
326377266186SHannes Reinecke 	raid_class_release(myrs_raid_template);
326477266186SHannes Reinecke }
326577266186SHannes Reinecke 
326677266186SHannes Reinecke module_init(myrs_init_module);
326777266186SHannes Reinecke module_exit(myrs_cleanup_module);
326877266186SHannes Reinecke 
326977266186SHannes Reinecke MODULE_DESCRIPTION("Mylex DAC960/AcceleRAID/eXtremeRAID driver (SCSI Interface)");
327077266186SHannes Reinecke MODULE_AUTHOR("Hannes Reinecke <hare@suse.com>");
327177266186SHannes Reinecke MODULE_LICENSE("GPL");
3272