1/*
2 * QLogic iSCSI HBA Driver
3 * Copyright (c)  2003-2006 QLogic Corporation
4 *
5 * See LICENSE.qla4xxx for copyright and licensing details.
6 */
7
8#include "ql4_def.h"
9
10
11/**
12 * qla4xxx_mailbox_command - issues mailbox commands
13 * @ha: Pointer to host adapter structure.
14 * @inCount: number of mailbox registers to load.
15 * @outCount: number of mailbox registers to return.
16 * @mbx_cmd: data pointer for mailbox in registers.
17 * @mbx_sts: data pointer for mailbox out registers.
18 *
19 * This routine sssue mailbox commands and waits for completion.
20 * If outCount is 0, this routine completes successfully WITHOUT waiting
21 * for the mailbox command to complete.
22 **/
23static int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount,
24				   uint8_t outCount, uint32_t *mbx_cmd,
25				   uint32_t *mbx_sts)
26{
27	int status = QLA_ERROR;
28	uint8_t i;
29	u_long wait_count;
30	uint32_t intr_status;
31	unsigned long flags = 0;
32
33	/* Make sure that pointers are valid */
34	if (!mbx_cmd || !mbx_sts) {
35		DEBUG2(printk("scsi%ld: %s: Invalid mbx_cmd or mbx_sts "
36			      "pointer\n", ha->host_no, __func__));
37		return status;
38	}
39	/* Mailbox code active */
40	wait_count = MBOX_TOV * 100;
41
42	while (wait_count--) {
43		mutex_lock(&ha->mbox_sem);
44		if (!test_bit(AF_MBOX_COMMAND, &ha->flags)) {
45			set_bit(AF_MBOX_COMMAND, &ha->flags);
46			mutex_unlock(&ha->mbox_sem);
47			break;
48		}
49		mutex_unlock(&ha->mbox_sem);
50		if (!wait_count) {
51			DEBUG2(printk("scsi%ld: %s: mbox_sem failed\n",
52				ha->host_no, __func__));
53			return status;
54		}
55		msleep(10);
56	}
57
58	/* To prevent overwriting mailbox registers for a command that has
59	 * not yet been serviced, check to see if a previously issued
60	 * mailbox command is interrupting.
61	 * -----------------------------------------------------------------
62	 */
63	spin_lock_irqsave(&ha->hardware_lock, flags);
64	intr_status = readl(&ha->reg->ctrl_status);
65	if (intr_status & CSR_SCSI_PROCESSOR_INTR) {
66		/* Service existing interrupt */
67		qla4xxx_interrupt_service_routine(ha, intr_status);
68		clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
69	}
70
71	/* Send the mailbox command to the firmware */
72	ha->mbox_status_count = outCount;
73	for (i = 0; i < outCount; i++)
74		ha->mbox_status[i] = 0;
75
76	/* Load all mailbox registers, except mailbox 0. */
77	for (i = 1; i < inCount; i++)
78		writel(mbx_cmd[i], &ha->reg->mailbox[i]);
79
80	/* Wakeup firmware  */
81	writel(mbx_cmd[0], &ha->reg->mailbox[0]);
82	readl(&ha->reg->mailbox[0]);
83	writel(set_rmask(CSR_INTR_RISC), &ha->reg->ctrl_status);
84	readl(&ha->reg->ctrl_status);
85	spin_unlock_irqrestore(&ha->hardware_lock, flags);
86
87	/* Wait for completion */
88
89	/*
90	 * If we don't want status, don't wait for the mailbox command to
91	 * complete.  For example, MBOX_CMD_RESET_FW doesn't return status,
92	 * you must poll the inbound Interrupt Mask for completion.
93	 */
94	if (outCount == 0) {
95		status = QLA_SUCCESS;
96		goto mbox_exit;
97	}
98	/* Wait for command to complete */
99	wait_count = jiffies + MBOX_TOV * HZ;
100	while (test_bit(AF_MBOX_COMMAND_DONE, &ha->flags) == 0) {
101		if (time_after_eq(jiffies, wait_count))
102			break;
103
104		spin_lock_irqsave(&ha->hardware_lock, flags);
105		intr_status = readl(&ha->reg->ctrl_status);
106		if (intr_status & INTR_PENDING) {
107			/*
108			 * Service the interrupt.
109			 * The ISR will save the mailbox status registers
110			 * to a temporary storage location in the adapter
111			 * structure.
112			 */
113			ha->mbox_status_count = outCount;
114			qla4xxx_interrupt_service_routine(ha, intr_status);
115		}
116		spin_unlock_irqrestore(&ha->hardware_lock, flags);
117		msleep(10);
118	}
119
120	/* Check for mailbox timeout. */
121	if (!test_bit(AF_MBOX_COMMAND_DONE, &ha->flags)) {
122		DEBUG2(printk("scsi%ld: Mailbox Cmd 0x%08X timed out ...,"
123			      " Scheduling Adapter Reset\n", ha->host_no,
124			      mbx_cmd[0]));
125		ha->mailbox_timeout_count++;
126		mbx_sts[0] = (-1);
127		set_bit(DPC_RESET_HA, &ha->dpc_flags);
128		goto mbox_exit;
129	}
130
131	/*
132	 * Copy the mailbox out registers to the caller's mailbox in/out
133	 * structure.
134	 */
135	spin_lock_irqsave(&ha->hardware_lock, flags);
136	for (i = 0; i < outCount; i++)
137		mbx_sts[i] = ha->mbox_status[i];
138
139	/* Set return status and error flags (if applicable). */
140	switch (ha->mbox_status[0]) {
141	case MBOX_STS_COMMAND_COMPLETE:
142		status = QLA_SUCCESS;
143		break;
144
145	case MBOX_STS_INTERMEDIATE_COMPLETION:
146		status = QLA_SUCCESS;
147		break;
148
149	case MBOX_STS_BUSY:
150		DEBUG2( printk("scsi%ld: %s: Cmd = %08X, ISP BUSY\n",
151			       ha->host_no, __func__, mbx_cmd[0]));
152		ha->mailbox_timeout_count++;
153		break;
154
155	default:
156		DEBUG2(printk("scsi%ld: %s: **** FAILED, cmd = %08X, "
157			      "sts = %08X ****\n", ha->host_no, __func__,
158			      mbx_cmd[0], mbx_sts[0]));
159		break;
160	}
161	spin_unlock_irqrestore(&ha->hardware_lock, flags);
162
163mbox_exit:
164	mutex_lock(&ha->mbox_sem);
165	clear_bit(AF_MBOX_COMMAND, &ha->flags);
166	mutex_unlock(&ha->mbox_sem);
167	clear_bit(AF_MBOX_COMMAND_DONE, &ha->flags);
168
169	return status;
170}
171
172
173
174/**
175 * qla4xxx_initialize_fw_cb - initializes firmware control block.
176 * @ha: Pointer to host adapter structure.
177 **/
178int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
179{
180	struct init_fw_ctrl_blk *init_fw_cb;
181	dma_addr_t init_fw_cb_dma;
182	uint32_t mbox_cmd[MBOX_REG_COUNT];
183	uint32_t mbox_sts[MBOX_REG_COUNT];
184	int status = QLA_ERROR;
185
186	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
187					sizeof(struct init_fw_ctrl_blk),
188					&init_fw_cb_dma, GFP_KERNEL);
189	if (init_fw_cb == NULL) {
190		DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n",
191			      ha->host_no, __func__));
192		return 10;
193	}
194	memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk));
195
196	/* Get Initialize Firmware Control Block. */
197	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
198	memset(&mbox_sts, 0, sizeof(mbox_sts));
199	mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
200	mbox_cmd[2] = LSDW(init_fw_cb_dma);
201	mbox_cmd[3] = MSDW(init_fw_cb_dma);
202	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
203	    QLA_SUCCESS) {
204		dma_free_coherent(&ha->pdev->dev,
205				  sizeof(struct init_fw_ctrl_blk),
206				  init_fw_cb, init_fw_cb_dma);
207		return status;
208	}
209
210	/* Initialize request and response queues. */
211	qla4xxx_init_rings(ha);
212
213	/* Fill in the request and response queue information. */
214	init_fw_cb->ReqQConsumerIndex = cpu_to_le16(ha->request_out);
215	init_fw_cb->ComplQProducerIndex = cpu_to_le16(ha->response_in);
216	init_fw_cb->ReqQLen = __constant_cpu_to_le16(REQUEST_QUEUE_DEPTH);
217	init_fw_cb->ComplQLen = __constant_cpu_to_le16(RESPONSE_QUEUE_DEPTH);
218	init_fw_cb->ReqQAddrLo = cpu_to_le32(LSDW(ha->request_dma));
219	init_fw_cb->ReqQAddrHi = cpu_to_le32(MSDW(ha->request_dma));
220	init_fw_cb->ComplQAddrLo = cpu_to_le32(LSDW(ha->response_dma));
221	init_fw_cb->ComplQAddrHi = cpu_to_le32(MSDW(ha->response_dma));
222	init_fw_cb->ShadowRegBufAddrLo =
223		cpu_to_le32(LSDW(ha->shadow_regs_dma));
224	init_fw_cb->ShadowRegBufAddrHi =
225		cpu_to_le32(MSDW(ha->shadow_regs_dma));
226
227	/* Set up required options. */
228	init_fw_cb->FwOptions |=
229		__constant_cpu_to_le16(FWOPT_SESSION_MODE |
230				       FWOPT_INITIATOR_MODE);
231	init_fw_cb->FwOptions &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
232
233	/* Save some info in adapter structure. */
234	ha->firmware_options = le16_to_cpu(init_fw_cb->FwOptions);
235	ha->tcp_options = le16_to_cpu(init_fw_cb->TCPOptions);
236	ha->heartbeat_interval = init_fw_cb->HeartbeatInterval;
237	memcpy(ha->ip_address, init_fw_cb->IPAddr,
238	       min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
239	memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
240	       min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
241	memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
242	       min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
243	memcpy(ha->name_string, init_fw_cb->iSCSINameString,
244	       min(sizeof(ha->name_string),
245		   sizeof(init_fw_cb->iSCSINameString)));
246	memcpy(ha->alias, init_fw_cb->Alias,
247	       min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));
248
249	/* Save Command Line Paramater info */
250	ha->port_down_retry_count = le16_to_cpu(init_fw_cb->KeepAliveTimeout);
251	ha->discovery_wait = ql4xdiscoverywait;
252
253	/* Send Initialize Firmware Control Block. */
254	mbox_cmd[0] = MBOX_CMD_INITIALIZE_FIRMWARE;
255	mbox_cmd[1] = 0;
256	mbox_cmd[2] = LSDW(init_fw_cb_dma);
257	mbox_cmd[3] = MSDW(init_fw_cb_dma);
258	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) ==
259	    QLA_SUCCESS)
260		status = QLA_SUCCESS;
261	 else {
262		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_INITIALIZE_FIRMWARE "
263			      "failed w/ status %04X\n", ha->host_no, __func__,
264			      mbox_sts[0]));
265	}
266	dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk),
267			  init_fw_cb, init_fw_cb_dma);
268
269	return status;
270}
271
272/**
273 * qla4xxx_get_dhcp_ip_address - gets HBA ip address via DHCP
274 * @ha: Pointer to host adapter structure.
275 **/
276int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha)
277{
278	struct init_fw_ctrl_blk *init_fw_cb;
279	dma_addr_t init_fw_cb_dma;
280	uint32_t mbox_cmd[MBOX_REG_COUNT];
281	uint32_t mbox_sts[MBOX_REG_COUNT];
282
283	init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
284					sizeof(struct init_fw_ctrl_blk),
285					&init_fw_cb_dma, GFP_KERNEL);
286	if (init_fw_cb == NULL) {
287		printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no,
288		       __func__);
289		return 10;
290	}
291
292	/* Get Initialize Firmware Control Block. */
293	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
294	memset(&mbox_sts, 0, sizeof(mbox_sts));
295	memset(init_fw_cb, 0, sizeof(struct init_fw_ctrl_blk));
296	mbox_cmd[0] = MBOX_CMD_GET_INIT_FW_CTRL_BLOCK;
297	mbox_cmd[2] = LSDW(init_fw_cb_dma);
298	mbox_cmd[3] = MSDW(init_fw_cb_dma);
299
300	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
301	    QLA_SUCCESS) {
302		DEBUG2(printk("scsi%ld: %s: Failed to get init_fw_ctrl_blk\n",
303			      ha->host_no, __func__));
304		dma_free_coherent(&ha->pdev->dev,
305				  sizeof(struct init_fw_ctrl_blk),
306				  init_fw_cb, init_fw_cb_dma);
307		return QLA_ERROR;
308	}
309
310	/* Save IP Address. */
311	memcpy(ha->ip_address, init_fw_cb->IPAddr,
312	       min(sizeof(ha->ip_address), sizeof(init_fw_cb->IPAddr)));
313	memcpy(ha->subnet_mask, init_fw_cb->SubnetMask,
314	       min(sizeof(ha->subnet_mask), sizeof(init_fw_cb->SubnetMask)));
315	memcpy(ha->gateway, init_fw_cb->GatewayIPAddr,
316	       min(sizeof(ha->gateway), sizeof(init_fw_cb->GatewayIPAddr)));
317
318	dma_free_coherent(&ha->pdev->dev, sizeof(struct init_fw_ctrl_blk),
319			  init_fw_cb, init_fw_cb_dma);
320
321	return QLA_SUCCESS;
322}
323
324/**
325 * qla4xxx_get_firmware_state - gets firmware state of HBA
326 * @ha: Pointer to host adapter structure.
327 **/
328int qla4xxx_get_firmware_state(struct scsi_qla_host * ha)
329{
330	uint32_t mbox_cmd[MBOX_REG_COUNT];
331	uint32_t mbox_sts[MBOX_REG_COUNT];
332
333	/* Get firmware version */
334	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
335	memset(&mbox_sts, 0, sizeof(mbox_sts));
336	mbox_cmd[0] = MBOX_CMD_GET_FW_STATE;
337	if (qla4xxx_mailbox_command(ha, 1, 4, &mbox_cmd[0], &mbox_sts[0]) !=
338	    QLA_SUCCESS) {
339		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATE failed w/ "
340			      "status %04X\n", ha->host_no, __func__,
341			      mbox_sts[0]));
342		return QLA_ERROR;
343	}
344	ha->firmware_state = mbox_sts[1];
345	ha->board_id = mbox_sts[2];
346	ha->addl_fw_state = mbox_sts[3];
347	DEBUG2(printk("scsi%ld: %s firmware_state=0x%x\n",
348		      ha->host_no, __func__, ha->firmware_state);)
349
350		return QLA_SUCCESS;
351}
352
353/**
354 * qla4xxx_get_firmware_status - retrieves firmware status
355 * @ha: Pointer to host adapter structure.
356 **/
357int qla4xxx_get_firmware_status(struct scsi_qla_host * ha)
358{
359	uint32_t mbox_cmd[MBOX_REG_COUNT];
360	uint32_t mbox_sts[MBOX_REG_COUNT];
361
362	/* Get firmware version */
363	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
364	memset(&mbox_sts, 0, sizeof(mbox_sts));
365	mbox_cmd[0] = MBOX_CMD_GET_FW_STATUS;
366	if (qla4xxx_mailbox_command(ha, 1, 3, &mbox_cmd[0], &mbox_sts[0]) !=
367	    QLA_SUCCESS) {
368		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_FW_STATUS failed w/ "
369			      "status %04X\n", ha->host_no, __func__,
370			      mbox_sts[0]));
371		return QLA_ERROR;
372	}
373
374	/* High-water mark of IOCBs */
375	ha->iocb_hiwat = mbox_sts[2];
376	if (ha->iocb_hiwat > IOCB_HIWAT_CUSHION)
377		ha->iocb_hiwat -= IOCB_HIWAT_CUSHION;
378	else
379		dev_info(&ha->pdev->dev, "WARNING!!!  You have less than %d "
380			   "firmare IOCBs available (%d).\n",
381			   IOCB_HIWAT_CUSHION, ha->iocb_hiwat);
382
383	return QLA_SUCCESS;
384}
385
386/**
387 * qla4xxx_get_fwddb_entry - retrieves firmware ddb entry
388 * @ha: Pointer to host adapter structure.
389 * @fw_ddb_index: Firmware's device database index
390 * @fw_ddb_entry: Pointer to firmware's device database entry structure
391 * @num_valid_ddb_entries: Pointer to number of valid ddb entries
392 * @next_ddb_index: Pointer to next valid device database index
393 * @fw_ddb_device_state: Pointer to device state
394 **/
395int qla4xxx_get_fwddb_entry(struct scsi_qla_host *ha,
396			    uint16_t fw_ddb_index,
397			    struct dev_db_entry *fw_ddb_entry,
398			    dma_addr_t fw_ddb_entry_dma,
399			    uint32_t *num_valid_ddb_entries,
400			    uint32_t *next_ddb_index,
401			    uint32_t *fw_ddb_device_state,
402			    uint32_t *conn_err_detail,
403			    uint16_t *tcp_source_port_num,
404			    uint16_t *connection_id)
405{
406	int status = QLA_ERROR;
407	uint32_t mbox_cmd[MBOX_REG_COUNT];
408	uint32_t mbox_sts[MBOX_REG_COUNT];
409
410	/* Make sure the device index is valid */
411	if (fw_ddb_index >= MAX_DDB_ENTRIES) {
412		DEBUG2(printk("scsi%ld: %s: index [%d] out of range.\n",
413			      ha->host_no, __func__, fw_ddb_index));
414		goto exit_get_fwddb;
415	}
416	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
417	memset(&mbox_sts, 0, sizeof(mbox_sts));
418	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY;
419	mbox_cmd[1] = (uint32_t) fw_ddb_index;
420	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
421	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
422	if (qla4xxx_mailbox_command(ha, 4, 7, &mbox_cmd[0], &mbox_sts[0]) ==
423	    QLA_ERROR) {
424		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_GET_DATABASE_ENTRY failed"
425			      " with status 0x%04X\n", ha->host_no, __func__,
426			      mbox_sts[0]));
427		goto exit_get_fwddb;
428	}
429	if (fw_ddb_index != mbox_sts[1]) {
430		DEBUG2(printk("scsi%ld: %s: index mismatch [%d] != [%d].\n",
431			      ha->host_no, __func__, fw_ddb_index,
432			      mbox_sts[1]));
433		goto exit_get_fwddb;
434	}
435	if (fw_ddb_entry) {
436		dev_info(&ha->pdev->dev, "DDB[%d] MB0 %04x Tot %d Next %d "
437			   "State %04x ConnErr %08x %d.%d.%d.%d:%04d \"%s\"\n",
438			   fw_ddb_index, mbox_sts[0], mbox_sts[2], mbox_sts[3],
439			   mbox_sts[4], mbox_sts[5], fw_ddb_entry->ipAddr[0],
440			   fw_ddb_entry->ipAddr[1], fw_ddb_entry->ipAddr[2],
441			   fw_ddb_entry->ipAddr[3],
442			   le16_to_cpu(fw_ddb_entry->portNumber),
443			   fw_ddb_entry->iscsiName);
444	}
445	if (num_valid_ddb_entries)
446		*num_valid_ddb_entries = mbox_sts[2];
447	if (next_ddb_index)
448		*next_ddb_index = mbox_sts[3];
449	if (fw_ddb_device_state)
450		*fw_ddb_device_state = mbox_sts[4];
451
452	/*
453	 * RA: This mailbox has been changed to pass connection error and
454	 * details.  Its true for ISP4010 as per Version E - Not sure when it
455	 * was changed.	 Get the time2wait from the fw_dd_entry field :
456	 * default_time2wait which we call it as minTime2Wait DEV_DB_ENTRY
457	 * struct.
458	 */
459	if (conn_err_detail)
460		*conn_err_detail = mbox_sts[5];
461	if (tcp_source_port_num)
462		*tcp_source_port_num = (uint16_t) mbox_sts[6] >> 16;
463	if (connection_id)
464		*connection_id = (uint16_t) mbox_sts[6] & 0x00FF;
465	status = QLA_SUCCESS;
466
467exit_get_fwddb:
468	return status;
469}
470
471/**
472 * qla4xxx_set_fwddb_entry - sets a ddb entry.
473 * @ha: Pointer to host adapter structure.
474 * @fw_ddb_index: Firmware's device database index
475 * @fw_ddb_entry: Pointer to firmware's ddb entry structure, or NULL.
476 *
477 * This routine initializes or updates the adapter's device database
478 * entry for the specified device. It also triggers a login for the
479 * specified device. Therefore, it may also be used as a secondary
480 * login routine when a NULL pointer is specified for the fw_ddb_entry.
481 **/
482int qla4xxx_set_ddb_entry(struct scsi_qla_host * ha, uint16_t fw_ddb_index,
483			  dma_addr_t fw_ddb_entry_dma)
484{
485	uint32_t mbox_cmd[MBOX_REG_COUNT];
486	uint32_t mbox_sts[MBOX_REG_COUNT];
487
488	/* Do not wait for completion. The firmware will send us an
489	 * ASTS_DATABASE_CHANGED (0x8014) to notify us of the login status.
490	 */
491	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
492	memset(&mbox_sts, 0, sizeof(mbox_sts));
493
494	mbox_cmd[0] = MBOX_CMD_SET_DATABASE_ENTRY;
495	mbox_cmd[1] = (uint32_t) fw_ddb_index;
496	mbox_cmd[2] = LSDW(fw_ddb_entry_dma);
497	mbox_cmd[3] = MSDW(fw_ddb_entry_dma);
498	return qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]);
499}
500
501
502/**
503 * qla4xxx_get_crash_record - retrieves crash record.
504 * @ha: Pointer to host adapter structure.
505 *
506 * This routine retrieves a crash record from the QLA4010 after an 8002h aen.
507 **/
508void qla4xxx_get_crash_record(struct scsi_qla_host * ha)
509{
510	uint32_t mbox_cmd[MBOX_REG_COUNT];
511	uint32_t mbox_sts[MBOX_REG_COUNT];
512	struct crash_record *crash_record = NULL;
513	dma_addr_t crash_record_dma = 0;
514	uint32_t crash_record_size = 0;
515	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
516	memset(&mbox_sts, 0, sizeof(mbox_cmd));
517
518	/* Get size of crash record. */
519	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
520	if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
521	    QLA_SUCCESS) {
522		DEBUG2(printk("scsi%ld: %s: ERROR: Unable to retrieve size!\n",
523			      ha->host_no, __func__));
524		goto exit_get_crash_record;
525	}
526	crash_record_size = mbox_sts[4];
527	if (crash_record_size == 0) {
528		DEBUG2(printk("scsi%ld: %s: ERROR: Crash record size is 0!\n",
529			      ha->host_no, __func__));
530		goto exit_get_crash_record;
531	}
532
533	/* Alloc Memory for Crash Record. */
534	crash_record = dma_alloc_coherent(&ha->pdev->dev, crash_record_size,
535					  &crash_record_dma, GFP_KERNEL);
536	if (crash_record == NULL)
537		goto exit_get_crash_record;
538
539	/* Get Crash Record. */
540	mbox_cmd[0] = MBOX_CMD_GET_CRASH_RECORD;
541	mbox_cmd[2] = LSDW(crash_record_dma);
542	mbox_cmd[3] = MSDW(crash_record_dma);
543	mbox_cmd[4] = crash_record_size;
544	if (qla4xxx_mailbox_command(ha, 5, 5, &mbox_cmd[0], &mbox_sts[0]) !=
545	    QLA_SUCCESS)
546		goto exit_get_crash_record;
547
548	/* Dump Crash Record. */
549
550exit_get_crash_record:
551	if (crash_record)
552		dma_free_coherent(&ha->pdev->dev, crash_record_size,
553				  crash_record, crash_record_dma);
554}
555
556
557/**
558 * qla4xxx_reset_lun - issues LUN Reset
559 * @ha: Pointer to host adapter structure.
560 * @db_entry: Pointer to device database entry
561 * @un_entry: Pointer to lun entry structure
562 *
563 * This routine performs a LUN RESET on the specified target/lun.
564 * The caller must ensure that the ddb_entry and lun_entry pointers
565 * are valid before calling this routine.
566 **/
567int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry,
568		      int lun)
569{
570	uint32_t mbox_cmd[MBOX_REG_COUNT];
571	uint32_t mbox_sts[MBOX_REG_COUNT];
572	int status = QLA_SUCCESS;
573
574	DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no,
575		      ddb_entry->os_target_id, lun));
576
577	/*
578	 * Send lun reset command to ISP, so that the ISP will return all
579	 * outstanding requests with RESET status
580	 */
581	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
582	memset(&mbox_sts, 0, sizeof(mbox_sts));
583	mbox_cmd[0] = MBOX_CMD_LUN_RESET;
584	mbox_cmd[1] = ddb_entry->fw_ddb_index;
585	mbox_cmd[2] = lun << 8;
586	mbox_cmd[5] = 0x01;	/* Immediate Command Enable */
587	qla4xxx_mailbox_command(ha, 6, 1, &mbox_cmd[0], &mbox_sts[0]);
588	if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE &&
589	    mbox_sts[0] != MBOX_STS_COMMAND_ERROR)
590		status = QLA_ERROR;
591
592	return status;
593}
594
595
596int qla4xxx_get_flash(struct scsi_qla_host * ha, dma_addr_t dma_addr,
597		      uint32_t offset, uint32_t len)
598{
599	uint32_t mbox_cmd[MBOX_REG_COUNT];
600	uint32_t mbox_sts[MBOX_REG_COUNT];
601
602	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
603	memset(&mbox_sts, 0, sizeof(mbox_sts));
604	mbox_cmd[0] = MBOX_CMD_READ_FLASH;
605	mbox_cmd[1] = LSDW(dma_addr);
606	mbox_cmd[2] = MSDW(dma_addr);
607	mbox_cmd[3] = offset;
608	mbox_cmd[4] = len;
609	if (qla4xxx_mailbox_command(ha, 5, 2, &mbox_cmd[0], &mbox_sts[0]) !=
610	    QLA_SUCCESS) {
611		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_READ_FLASH, failed w/ "
612		    "status %04X %04X, offset %08x, len %08x\n", ha->host_no,
613		    __func__, mbox_sts[0], mbox_sts[1], offset, len));
614		return QLA_ERROR;
615	}
616	return QLA_SUCCESS;
617}
618
619/**
620 * qla4xxx_get_fw_version - gets firmware version
621 * @ha: Pointer to host adapter structure.
622 *
623 * Retrieves the firmware version on HBA. In QLA4010, mailboxes 2 & 3 may
624 * hold an address for data.  Make sure that we write 0 to those mailboxes,
625 * if unused.
626 **/
627int qla4xxx_get_fw_version(struct scsi_qla_host * ha)
628{
629	uint32_t mbox_cmd[MBOX_REG_COUNT];
630	uint32_t mbox_sts[MBOX_REG_COUNT];
631
632	/* Get firmware version. */
633	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
634	memset(&mbox_sts, 0, sizeof(mbox_sts));
635	mbox_cmd[0] = MBOX_CMD_ABOUT_FW;
636	if (qla4xxx_mailbox_command(ha, 4, 5, &mbox_cmd[0], &mbox_sts[0]) !=
637	    QLA_SUCCESS) {
638		DEBUG2(printk("scsi%ld: %s: MBOX_CMD_ABOUT_FW failed w/ "
639		    "status %04X\n", ha->host_no, __func__, mbox_sts[0]));
640		return QLA_ERROR;
641	}
642
643	/* Save firmware version information. */
644	ha->firmware_version[0] = mbox_sts[1];
645	ha->firmware_version[1] = mbox_sts[2];
646	ha->patch_number = mbox_sts[3];
647	ha->build_number = mbox_sts[4];
648
649	return QLA_SUCCESS;
650}
651
652static int qla4xxx_get_default_ddb(struct scsi_qla_host *ha,
653				   dma_addr_t dma_addr)
654{
655	uint32_t mbox_cmd[MBOX_REG_COUNT];
656	uint32_t mbox_sts[MBOX_REG_COUNT];
657
658	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
659	memset(&mbox_sts, 0, sizeof(mbox_sts));
660
661	mbox_cmd[0] = MBOX_CMD_GET_DATABASE_ENTRY_DEFAULTS;
662	mbox_cmd[2] = LSDW(dma_addr);
663	mbox_cmd[3] = MSDW(dma_addr);
664
665	if (qla4xxx_mailbox_command(ha, 4, 1, &mbox_cmd[0], &mbox_sts[0]) !=
666	    QLA_SUCCESS) {
667		DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
668		     ha->host_no, __func__, mbox_sts[0]));
669		return QLA_ERROR;
670	}
671	return QLA_SUCCESS;
672}
673
674static int qla4xxx_req_ddb_entry(struct scsi_qla_host *ha, uint32_t *ddb_index)
675{
676	uint32_t mbox_cmd[MBOX_REG_COUNT];
677	uint32_t mbox_sts[MBOX_REG_COUNT];
678
679	memset(&mbox_cmd, 0, sizeof(mbox_cmd));
680	memset(&mbox_sts, 0, sizeof(mbox_sts));
681
682	mbox_cmd[0] = MBOX_CMD_REQUEST_DATABASE_ENTRY;
683	mbox_cmd[1] = MAX_PRST_DEV_DB_ENTRIES;
684
685	if (qla4xxx_mailbox_command(ha, 2, 3, &mbox_cmd[0], &mbox_sts[0]) !=
686	    QLA_SUCCESS) {
687		if (mbox_sts[0] == MBOX_STS_COMMAND_ERROR) {
688			*ddb_index = mbox_sts[2];
689		} else {
690			DEBUG2(printk("scsi%ld: %s: failed status %04X\n",
691			     ha->host_no, __func__, mbox_sts[0]));
692			return QLA_ERROR;
693		}
694	} else {
695		*ddb_index = MAX_PRST_DEV_DB_ENTRIES;
696	}
697
698	return QLA_SUCCESS;
699}
700
701
702int qla4xxx_send_tgts(struct scsi_qla_host *ha, char *ip, uint16_t port)
703{
704	struct dev_db_entry *fw_ddb_entry;
705	dma_addr_t fw_ddb_entry_dma;
706	uint32_t ddb_index;
707	int ret_val = QLA_SUCCESS;
708
709
710	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev,
711					  sizeof(*fw_ddb_entry),
712					  &fw_ddb_entry_dma, GFP_KERNEL);
713	if (!fw_ddb_entry) {
714		DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
715			      ha->host_no, __func__));
716		ret_val = QLA_ERROR;
717		goto qla4xxx_send_tgts_exit;
718	}
719
720	ret_val = qla4xxx_get_default_ddb(ha, fw_ddb_entry_dma);
721	if (ret_val != QLA_SUCCESS)
722		goto qla4xxx_send_tgts_exit;
723
724	ret_val = qla4xxx_req_ddb_entry(ha, &ddb_index);
725	if (ret_val != QLA_SUCCESS)
726		goto qla4xxx_send_tgts_exit;
727
728	memset((void *)fw_ddb_entry->iSCSIAlias, 0,
729	       sizeof(fw_ddb_entry->iSCSIAlias));
730
731	memset((void *)fw_ddb_entry->iscsiName, 0,
732	       sizeof(fw_ddb_entry->iscsiName));
733
734	memset((void *)fw_ddb_entry->ipAddr, 0, sizeof(fw_ddb_entry->ipAddr));
735	memset((void *)fw_ddb_entry->targetAddr, 0,
736	       sizeof(fw_ddb_entry->targetAddr));
737
738	fw_ddb_entry->options = (DDB_OPT_DISC_SESSION | DDB_OPT_TARGET);
739	fw_ddb_entry->portNumber = cpu_to_le16(ntohs(port));
740
741	fw_ddb_entry->ipAddr[0] = *ip;
742	fw_ddb_entry->ipAddr[1] = *(ip + 1);
743	fw_ddb_entry->ipAddr[2] = *(ip + 2);
744	fw_ddb_entry->ipAddr[3] = *(ip + 3);
745
746	ret_val = qla4xxx_set_ddb_entry(ha, ddb_index, fw_ddb_entry_dma);
747
748qla4xxx_send_tgts_exit:
749	dma_free_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
750			  fw_ddb_entry, fw_ddb_entry_dma);
751	return ret_val;
752}
753