xref: /onnv-gate/usr/src/uts/common/io/fibre-channel/fca/qlge/qlge_flash.c (revision 12073:05ba1c0d6140)
110997SSukumar.Swaminathan@Sun.COM /*
210997SSukumar.Swaminathan@Sun.COM  * CDDL HEADER START
310997SSukumar.Swaminathan@Sun.COM  *
410997SSukumar.Swaminathan@Sun.COM  * The contents of this file are subject to the terms of the
510997SSukumar.Swaminathan@Sun.COM  * Common Development and Distribution License (the "License").
610997SSukumar.Swaminathan@Sun.COM  * You may not use this file except in compliance with the License.
710997SSukumar.Swaminathan@Sun.COM  *
810997SSukumar.Swaminathan@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910997SSukumar.Swaminathan@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010997SSukumar.Swaminathan@Sun.COM  * See the License for the specific language governing permissions
1110997SSukumar.Swaminathan@Sun.COM  * and limitations under the License.
1210997SSukumar.Swaminathan@Sun.COM  *
1310997SSukumar.Swaminathan@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410997SSukumar.Swaminathan@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510997SSukumar.Swaminathan@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610997SSukumar.Swaminathan@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710997SSukumar.Swaminathan@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810997SSukumar.Swaminathan@Sun.COM  *
1910997SSukumar.Swaminathan@Sun.COM  * CDDL HEADER END
2010997SSukumar.Swaminathan@Sun.COM  */
2110997SSukumar.Swaminathan@Sun.COM 
2210997SSukumar.Swaminathan@Sun.COM /*
23*12073SSukumar.Swaminathan@Sun.COM  * Copyright 2010 QLogic Corporation. All rights reserved.
2410997SSukumar.Swaminathan@Sun.COM  */
2510997SSukumar.Swaminathan@Sun.COM 
2610997SSukumar.Swaminathan@Sun.COM #include <qlge.h>
2710997SSukumar.Swaminathan@Sun.COM /*
2810997SSukumar.Swaminathan@Sun.COM  * Local Function Prototypes.
2910997SSukumar.Swaminathan@Sun.COM  */
3010997SSukumar.Swaminathan@Sun.COM static int ql_read_flash(qlge_t *, uint32_t, uint32_t *);
3110997SSukumar.Swaminathan@Sun.COM static int ql_write_flash(qlge_t *, uint32_t, uint32_t);
3210997SSukumar.Swaminathan@Sun.COM static int ql_protect_flash(qlge_t *);
3310997SSukumar.Swaminathan@Sun.COM static int ql_unprotect_flash(qlge_t *);
3410997SSukumar.Swaminathan@Sun.COM 
3510997SSukumar.Swaminathan@Sun.COM /*
3610997SSukumar.Swaminathan@Sun.COM  * ql_flash_id
3710997SSukumar.Swaminathan@Sun.COM  * The flash memory chip exports 3 ID bytes in the order of manufacturer, id,
3810997SSukumar.Swaminathan@Sun.COM  * capability
3910997SSukumar.Swaminathan@Sun.COM  */
4010997SSukumar.Swaminathan@Sun.COM int
ql_flash_id(qlge_t * qlge)4110997SSukumar.Swaminathan@Sun.COM ql_flash_id(qlge_t *qlge)
4210997SSukumar.Swaminathan@Sun.COM {
4310997SSukumar.Swaminathan@Sun.COM 	int rval;
4410997SSukumar.Swaminathan@Sun.COM 	uint32_t fdata = 0;
4510997SSukumar.Swaminathan@Sun.COM 
4610997SSukumar.Swaminathan@Sun.COM 	/*
4710997SSukumar.Swaminathan@Sun.COM 	 * Send Restore command (0xAB) to release Flash from
4810997SSukumar.Swaminathan@Sun.COM 	 * possible deep power down state
4910997SSukumar.Swaminathan@Sun.COM 	 */
5010997SSukumar.Swaminathan@Sun.COM 	rval = ql_read_flash(qlge, FLASH_CONF_ADDR | 0x300 | FLASH_RES_CMD,
5110997SSukumar.Swaminathan@Sun.COM 	    &fdata);
5210997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("%s(%d) flash electronic signature is %x \n",
5310997SSukumar.Swaminathan@Sun.COM 	    __func__, qlge->instance, fdata));
5410997SSukumar.Swaminathan@Sun.COM 	fdata = 0;
5510997SSukumar.Swaminathan@Sun.COM 
5610997SSukumar.Swaminathan@Sun.COM 	/* 0x9F */
5710997SSukumar.Swaminathan@Sun.COM 	rval = ql_read_flash(qlge, FLASH_CONF_ADDR | 0x0400 | FLASH_RDID_CMD,
5810997SSukumar.Swaminathan@Sun.COM 	    &fdata);
5910997SSukumar.Swaminathan@Sun.COM 
6010997SSukumar.Swaminathan@Sun.COM 	if ((rval != DDI_SUCCESS) || (fdata == 0)) {
6110997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) read_flash failed 0x%x.",
6210997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance, fdata);
6310997SSukumar.Swaminathan@Sun.COM 	} else {
6410997SSukumar.Swaminathan@Sun.COM 		qlge->flash_info.flash_manuf = LSB(LSW(fdata));
6510997SSukumar.Swaminathan@Sun.COM 		qlge->flash_info.flash_id = MSB(LSW(fdata));
6610997SSukumar.Swaminathan@Sun.COM 		qlge->flash_info.flash_cap = LSB(MSW(fdata));
6710997SSukumar.Swaminathan@Sun.COM 		QL_PRINT(DBG_FLASH, ("%s(%d) flash manufacturer 0x%x,"
6810997SSukumar.Swaminathan@Sun.COM 		    " flash id 0x%x, flash cap 0x%x\n",
6910997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance,
7010997SSukumar.Swaminathan@Sun.COM 		    qlge->flash_info.flash_manuf, qlge->flash_info.flash_id,
7110997SSukumar.Swaminathan@Sun.COM 		    qlge->flash_info.flash_cap));
7210997SSukumar.Swaminathan@Sun.COM 	}
7310997SSukumar.Swaminathan@Sun.COM 	return (rval);
7410997SSukumar.Swaminathan@Sun.COM }
7510997SSukumar.Swaminathan@Sun.COM 
7610997SSukumar.Swaminathan@Sun.COM /*
7710997SSukumar.Swaminathan@Sun.COM  * qlge_dump_fcode
7810997SSukumar.Swaminathan@Sun.COM  * Dumps fcode from flash.
7910997SSukumar.Swaminathan@Sun.COM  */
8010997SSukumar.Swaminathan@Sun.COM int
qlge_dump_fcode(qlge_t * qlge,uint8_t * dp,uint32_t size,uint32_t startpos)8110997SSukumar.Swaminathan@Sun.COM qlge_dump_fcode(qlge_t *qlge, uint8_t *dp, uint32_t size, uint32_t startpos)
8210997SSukumar.Swaminathan@Sun.COM {
8310997SSukumar.Swaminathan@Sun.COM 	uint32_t cnt, data, addr;
8410997SSukumar.Swaminathan@Sun.COM 	int rval = DDI_SUCCESS;
8510997SSukumar.Swaminathan@Sun.COM 
8610997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("%s(%d) entered to read address %x, %x bytes\n",
8710997SSukumar.Swaminathan@Sun.COM 	    __func__, qlge->instance, startpos, size));
8810997SSukumar.Swaminathan@Sun.COM 
8910997SSukumar.Swaminathan@Sun.COM 	/* make sure startpos+size doesn't exceed flash */
9010997SSukumar.Swaminathan@Sun.COM 	if (size + startpos > qlge->fdesc.flash_size) {
9110997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) exceeded flash range, sz=%xh, stp=%xh,"
9210997SSukumar.Swaminathan@Sun.COM 		    " flsz=%xh", __func__, qlge->instance,
9310997SSukumar.Swaminathan@Sun.COM 		    size, startpos, qlge->fdesc.flash_size);
9410997SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
9510997SSukumar.Swaminathan@Sun.COM 	}
9610997SSukumar.Swaminathan@Sun.COM 
9710997SSukumar.Swaminathan@Sun.COM 	/* check start addr is 32 bit or 4 byte aligned for M25Pxx */
9810997SSukumar.Swaminathan@Sun.COM 	if ((startpos & 0x3) != 0) {
9910997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) incorrect buffer size alignment",
10010997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance);
10110997SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
10210997SSukumar.Swaminathan@Sun.COM 	}
10310997SSukumar.Swaminathan@Sun.COM 
10410997SSukumar.Swaminathan@Sun.COM 	/* adjust flash start addr for 32 bit words */
10510997SSukumar.Swaminathan@Sun.COM 	addr = startpos / 4;
10610997SSukumar.Swaminathan@Sun.COM 
10710997SSukumar.Swaminathan@Sun.COM 	/* Read fcode data from flash. */
10810997SSukumar.Swaminathan@Sun.COM 	cnt = startpos;
10910997SSukumar.Swaminathan@Sun.COM 	size += startpos;
11010997SSukumar.Swaminathan@Sun.COM 	while (cnt < size) {
11110997SSukumar.Swaminathan@Sun.COM 		/* Allow other system activity. */
11210997SSukumar.Swaminathan@Sun.COM 		if (cnt % 0x1000 == 0) {
11310997SSukumar.Swaminathan@Sun.COM 			drv_usecwait(1);
11410997SSukumar.Swaminathan@Sun.COM 		}
11510997SSukumar.Swaminathan@Sun.COM 		rval = ql_read_flash(qlge, addr++, &data);
11610997SSukumar.Swaminathan@Sun.COM 		if (rval != DDI_SUCCESS) {
11710997SSukumar.Swaminathan@Sun.COM 			break;
11810997SSukumar.Swaminathan@Sun.COM 		}
11910997SSukumar.Swaminathan@Sun.COM 		*dp++ = LSB(LSW(data));
12010997SSukumar.Swaminathan@Sun.COM 		*dp++ = MSB(LSW(data));
12110997SSukumar.Swaminathan@Sun.COM 		*dp++ = LSB(MSW(data));
12210997SSukumar.Swaminathan@Sun.COM 		*dp++ = MSB(MSW(data));
12310997SSukumar.Swaminathan@Sun.COM 		cnt += 4;
12410997SSukumar.Swaminathan@Sun.COM 	}
12510997SSukumar.Swaminathan@Sun.COM 
12610997SSukumar.Swaminathan@Sun.COM 	if (rval != DDI_SUCCESS) {
12710997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "failed, rval = %xh", rval);
12810997SSukumar.Swaminathan@Sun.COM 	}
12910997SSukumar.Swaminathan@Sun.COM 	return (rval);
13010997SSukumar.Swaminathan@Sun.COM }
13110997SSukumar.Swaminathan@Sun.COM 
13210997SSukumar.Swaminathan@Sun.COM int
ql_erase_and_write_to_flash(qlge_t * qlge,uint8_t * dp,uint32_t size,uint32_t faddr)13310997SSukumar.Swaminathan@Sun.COM ql_erase_and_write_to_flash(qlge_t *qlge, uint8_t *dp, uint32_t size,
13410997SSukumar.Swaminathan@Sun.COM     uint32_t faddr)
13510997SSukumar.Swaminathan@Sun.COM {
13610997SSukumar.Swaminathan@Sun.COM 	int rval = DDI_FAILURE;
13710997SSukumar.Swaminathan@Sun.COM 	uint32_t cnt, rest_addr, fdata;
13810997SSukumar.Swaminathan@Sun.COM 
13910997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("%s(%d) entered to write addr %x, %d bytes\n",
14010997SSukumar.Swaminathan@Sun.COM 	    __func__, qlge->instance, faddr, size));
14110997SSukumar.Swaminathan@Sun.COM 
14210997SSukumar.Swaminathan@Sun.COM 	/* start address must be 32 bit word aligned */
14310997SSukumar.Swaminathan@Sun.COM 	if ((faddr & 0x3) != 0) {
14410997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) incorrect buffer size alignment",
14510997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance);
14610997SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
14710997SSukumar.Swaminathan@Sun.COM 	}
14810997SSukumar.Swaminathan@Sun.COM 
14910997SSukumar.Swaminathan@Sun.COM 	/* setup mask of address range within a sector */
15010997SSukumar.Swaminathan@Sun.COM 	rest_addr = (qlge->fdesc.block_size - 1) >> 2;
15110997SSukumar.Swaminathan@Sun.COM 
15210997SSukumar.Swaminathan@Sun.COM 	faddr = faddr >> 2;	/* flash gets 32 bit words */
15310997SSukumar.Swaminathan@Sun.COM 
15410997SSukumar.Swaminathan@Sun.COM 	/*
15510997SSukumar.Swaminathan@Sun.COM 	 * Write data to flash.
15610997SSukumar.Swaminathan@Sun.COM 	 */
15710997SSukumar.Swaminathan@Sun.COM 	cnt = 0;
15810997SSukumar.Swaminathan@Sun.COM 	size = (size + 3) >> 2;	/* Round up & convert to dwords */
15910997SSukumar.Swaminathan@Sun.COM 	while (cnt < size) {
16010997SSukumar.Swaminathan@Sun.COM 		/* Beginning of a sector? do a sector erase */
16110997SSukumar.Swaminathan@Sun.COM 		if ((faddr & rest_addr) == 0) {
16210997SSukumar.Swaminathan@Sun.COM 			fdata = (faddr & ~rest_addr) << 2;
16310997SSukumar.Swaminathan@Sun.COM 			fdata = (fdata & 0xff00) |
16410997SSukumar.Swaminathan@Sun.COM 			    (fdata << 16 & 0xff0000) |
16510997SSukumar.Swaminathan@Sun.COM 			    (fdata >> 16 & 0xff);
16610997SSukumar.Swaminathan@Sun.COM 			/* 64k bytes sector erase */
16710997SSukumar.Swaminathan@Sun.COM 			rval = ql_write_flash(qlge, /* 0xd8 */
16810997SSukumar.Swaminathan@Sun.COM 			    FLASH_CONF_ADDR | 0x0300 | qlge->fdesc.erase_cmd,
16910997SSukumar.Swaminathan@Sun.COM 			    fdata);
17010997SSukumar.Swaminathan@Sun.COM 
17110997SSukumar.Swaminathan@Sun.COM 			if (rval != DDI_SUCCESS) {
17210997SSukumar.Swaminathan@Sun.COM 				cmn_err(CE_WARN, "Unable to flash sector: "
17310997SSukumar.Swaminathan@Sun.COM 				    "address=%xh", faddr);
17410997SSukumar.Swaminathan@Sun.COM 				goto out;
17510997SSukumar.Swaminathan@Sun.COM 			}
17610997SSukumar.Swaminathan@Sun.COM 		}
17710997SSukumar.Swaminathan@Sun.COM 		/* Write data */
17810997SSukumar.Swaminathan@Sun.COM 		fdata = *dp++;
17910997SSukumar.Swaminathan@Sun.COM 		fdata |= *dp++ << 8;
18010997SSukumar.Swaminathan@Sun.COM 		fdata |= *dp++ << 16;
18110997SSukumar.Swaminathan@Sun.COM 		fdata |= *dp++ << 24;
18210997SSukumar.Swaminathan@Sun.COM 
18310997SSukumar.Swaminathan@Sun.COM 		rval = ql_write_flash(qlge, faddr, fdata);
18410997SSukumar.Swaminathan@Sun.COM 		if (rval != DDI_SUCCESS) {
18510997SSukumar.Swaminathan@Sun.COM 			cmn_err(CE_WARN, "Unable to program flash "
18610997SSukumar.Swaminathan@Sun.COM 			    "address=%xh data=%xh", faddr,
18710997SSukumar.Swaminathan@Sun.COM 			    *dp);
18810997SSukumar.Swaminathan@Sun.COM 			goto out;
18910997SSukumar.Swaminathan@Sun.COM 		}
19010997SSukumar.Swaminathan@Sun.COM 		cnt++;
19110997SSukumar.Swaminathan@Sun.COM 		faddr++;
19210997SSukumar.Swaminathan@Sun.COM 
19310997SSukumar.Swaminathan@Sun.COM 		/* Allow other system activity. */
19410997SSukumar.Swaminathan@Sun.COM 		if (cnt % 0x1000 == 0) {
19510997SSukumar.Swaminathan@Sun.COM 			qlge_delay(10000);
19610997SSukumar.Swaminathan@Sun.COM 		}
19710997SSukumar.Swaminathan@Sun.COM 	}
19810997SSukumar.Swaminathan@Sun.COM 	rval = DDI_SUCCESS;
19910997SSukumar.Swaminathan@Sun.COM out:
20010997SSukumar.Swaminathan@Sun.COM 	if (rval != DDI_SUCCESS) {
20110997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d failed=%xh",
20210997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance, rval);
20310997SSukumar.Swaminathan@Sun.COM 	}
20410997SSukumar.Swaminathan@Sun.COM 	return (rval);
20510997SSukumar.Swaminathan@Sun.COM }
20610997SSukumar.Swaminathan@Sun.COM 
20710997SSukumar.Swaminathan@Sun.COM void
get_sector_number(qlge_t * qlge,uint32_t faddr,uint32_t * psector)20810997SSukumar.Swaminathan@Sun.COM get_sector_number(qlge_t *qlge, uint32_t faddr, uint32_t *psector)
20910997SSukumar.Swaminathan@Sun.COM {
21010997SSukumar.Swaminathan@Sun.COM 	*psector = faddr / qlge->fdesc.block_size; /* 0x10000 */
21110997SSukumar.Swaminathan@Sun.COM }
21210997SSukumar.Swaminathan@Sun.COM 
21310997SSukumar.Swaminathan@Sun.COM /*
21410997SSukumar.Swaminathan@Sun.COM  * qlge_load_flash
21510997SSukumar.Swaminathan@Sun.COM  * Write "size" bytes from memory "dp" to flash address "faddr".
21610997SSukumar.Swaminathan@Sun.COM  * faddr = 32bit word flash address.
21710997SSukumar.Swaminathan@Sun.COM  */
21810997SSukumar.Swaminathan@Sun.COM int
qlge_load_flash(qlge_t * qlge,uint8_t * dp,uint32_t len,uint32_t faddr)21910997SSukumar.Swaminathan@Sun.COM qlge_load_flash(qlge_t *qlge, uint8_t *dp, uint32_t len, uint32_t faddr)
22010997SSukumar.Swaminathan@Sun.COM {
22110997SSukumar.Swaminathan@Sun.COM 	int rval = DDI_FAILURE;
22210997SSukumar.Swaminathan@Sun.COM 	uint32_t start_block, end_block;
22310997SSukumar.Swaminathan@Sun.COM 	uint32_t start_byte, end_byte;
22410997SSukumar.Swaminathan@Sun.COM 	uint32_t num;
22510997SSukumar.Swaminathan@Sun.COM 	uint32_t sector_size, addr_src, addr_desc;
22610997SSukumar.Swaminathan@Sun.COM 	uint8_t *temp;
22710997SSukumar.Swaminathan@Sun.COM 	caddr_t bp, bdesc;
22810997SSukumar.Swaminathan@Sun.COM 
22910997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("%s(%d) entered to write addr %x, %d bytes\n",
23010997SSukumar.Swaminathan@Sun.COM 	    __func__, qlge->instance, faddr, len));
23110997SSukumar.Swaminathan@Sun.COM 
23210997SSukumar.Swaminathan@Sun.COM 	sector_size = qlge->fdesc.block_size;
23310997SSukumar.Swaminathan@Sun.COM 
23410997SSukumar.Swaminathan@Sun.COM 	if (faddr > qlge->fdesc.flash_size) {
23510997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d): invalid flash write address %x",
23610997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance, faddr);
23710997SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
23810997SSukumar.Swaminathan@Sun.COM 	}
23910997SSukumar.Swaminathan@Sun.COM 	/* Get semaphore to access Flash Address and Flash Data Registers */
24010997SSukumar.Swaminathan@Sun.COM 	if (ql_sem_spinlock(qlge, QL_FLASH_SEM_MASK) != DDI_SUCCESS) {
24110997SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
24210997SSukumar.Swaminathan@Sun.COM 	}
24310997SSukumar.Swaminathan@Sun.COM 	temp = kmem_zalloc(sector_size, KM_SLEEP);
24410997SSukumar.Swaminathan@Sun.COM 	if (temp == NULL) {
24510997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d): Unable to allocate buffer",
24610997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance);
24710997SSukumar.Swaminathan@Sun.COM 		ql_sem_unlock(qlge, QL_FLASH_SEM_MASK);
24810997SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
24910997SSukumar.Swaminathan@Sun.COM 	}
25010997SSukumar.Swaminathan@Sun.COM 
25111016SSukumar.Swaminathan@Sun.COM 	(void) ql_unprotect_flash(qlge);
25210997SSukumar.Swaminathan@Sun.COM 
25310997SSukumar.Swaminathan@Sun.COM 	get_sector_number(qlge, faddr, &start_block);
25410997SSukumar.Swaminathan@Sun.COM 	get_sector_number(qlge, faddr + len - 1, &end_block);
25510997SSukumar.Swaminathan@Sun.COM 
25610997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("%s(%d) start_block %x, end_block %x\n",
25710997SSukumar.Swaminathan@Sun.COM 	    __func__, qlge->instance, start_block, end_block));
25810997SSukumar.Swaminathan@Sun.COM 
25910997SSukumar.Swaminathan@Sun.COM 	for (num = start_block; num <= end_block; num++) {
26010997SSukumar.Swaminathan@Sun.COM 		QL_PRINT(DBG_FLASH,
26110997SSukumar.Swaminathan@Sun.COM 		    ("%s(%d) sector_size 0x%x, sector read addr %x\n",
26210997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance, sector_size, num * sector_size));
26310997SSukumar.Swaminathan@Sun.COM 		/* read one whole sector flash data to buffer */
26410997SSukumar.Swaminathan@Sun.COM 		rval = qlge_dump_fcode(qlge, (uint8_t *)temp, sector_size,
26510997SSukumar.Swaminathan@Sun.COM 		    num * sector_size);
26610997SSukumar.Swaminathan@Sun.COM 
26710997SSukumar.Swaminathan@Sun.COM 		start_byte = num * sector_size;
26810997SSukumar.Swaminathan@Sun.COM 		end_byte = start_byte + sector_size -1;
26910997SSukumar.Swaminathan@Sun.COM 		if (start_byte < faddr)
27010997SSukumar.Swaminathan@Sun.COM 			start_byte = faddr;
27110997SSukumar.Swaminathan@Sun.COM 		if (end_byte > (faddr + len))
27210997SSukumar.Swaminathan@Sun.COM 			end_byte = (faddr + len - 1);
27310997SSukumar.Swaminathan@Sun.COM 
27410997SSukumar.Swaminathan@Sun.COM 		addr_src = start_byte - faddr;
27510997SSukumar.Swaminathan@Sun.COM 		addr_desc = start_byte - num * sector_size;
27610997SSukumar.Swaminathan@Sun.COM 		bp = (caddr_t)dp + addr_src;
27710997SSukumar.Swaminathan@Sun.COM 		bdesc = (caddr_t)temp + addr_desc;
27810997SSukumar.Swaminathan@Sun.COM 		bcopy(bp, bdesc, (end_byte - start_byte + 1));
27910997SSukumar.Swaminathan@Sun.COM 
28010997SSukumar.Swaminathan@Sun.COM 		/* write the whole sector data to flash */
28110997SSukumar.Swaminathan@Sun.COM 		if (ql_erase_and_write_to_flash(qlge, temp, sector_size,
28210997SSukumar.Swaminathan@Sun.COM 		    num * sector_size) != DDI_SUCCESS)
28310997SSukumar.Swaminathan@Sun.COM 			goto out;
28410997SSukumar.Swaminathan@Sun.COM 	}
28510997SSukumar.Swaminathan@Sun.COM 	rval = DDI_SUCCESS;
28610997SSukumar.Swaminathan@Sun.COM out:
28711016SSukumar.Swaminathan@Sun.COM 	(void) ql_protect_flash(qlge);
28810997SSukumar.Swaminathan@Sun.COM 	kmem_free(temp, sector_size);
28910997SSukumar.Swaminathan@Sun.COM 
29010997SSukumar.Swaminathan@Sun.COM 	ql_sem_unlock(qlge, QL_FLASH_SEM_MASK);
29110997SSukumar.Swaminathan@Sun.COM 
29210997SSukumar.Swaminathan@Sun.COM 	if (rval != DDI_SUCCESS) {
29310997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d failed=%xh",
29410997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance, rval);
29510997SSukumar.Swaminathan@Sun.COM 	}
29610997SSukumar.Swaminathan@Sun.COM 
29710997SSukumar.Swaminathan@Sun.COM 	return (rval);
29810997SSukumar.Swaminathan@Sun.COM }
29910997SSukumar.Swaminathan@Sun.COM 
30010997SSukumar.Swaminathan@Sun.COM 
30110997SSukumar.Swaminathan@Sun.COM /*
30210997SSukumar.Swaminathan@Sun.COM  * ql_check_pci
30310997SSukumar.Swaminathan@Sun.COM  * checks the passed buffer for a valid pci signature and
30410997SSukumar.Swaminathan@Sun.COM  * expected (and in range) pci length values.
30510997SSukumar.Swaminathan@Sun.COM  * On successful pci check, nextpos adjusted to next pci header.
30610997SSukumar.Swaminathan@Sun.COM  */
30710997SSukumar.Swaminathan@Sun.COM static int
ql_check_pci(qlge_t * qlge,uint8_t * buf,uint32_t * nextpos)30810997SSukumar.Swaminathan@Sun.COM ql_check_pci(qlge_t *qlge, uint8_t *buf, uint32_t *nextpos)
30910997SSukumar.Swaminathan@Sun.COM {
31010997SSukumar.Swaminathan@Sun.COM 	pci_header_t *pcih;
31110997SSukumar.Swaminathan@Sun.COM 	pci_data_t *pcid;
31210997SSukumar.Swaminathan@Sun.COM 	uint32_t doff;
31310997SSukumar.Swaminathan@Sun.COM 	uint8_t *pciinfo;
31410997SSukumar.Swaminathan@Sun.COM 	uint32_t image_size = 0;
31510997SSukumar.Swaminathan@Sun.COM 	int rval = CONTINUE_SEARCH;
31610997SSukumar.Swaminathan@Sun.COM 
31710997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("%s(%d) check image at 0x%x\n",
31810997SSukumar.Swaminathan@Sun.COM 	    __func__, qlge->instance, *nextpos));
31910997SSukumar.Swaminathan@Sun.COM 
32010997SSukumar.Swaminathan@Sun.COM 	if (buf != NULL) {
32110997SSukumar.Swaminathan@Sun.COM 		pciinfo = buf;
32210997SSukumar.Swaminathan@Sun.COM 	} else {
32310997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) failed, null buf ptr passed",
32410997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance);
32510997SSukumar.Swaminathan@Sun.COM 		return (STOP_SEARCH);
32610997SSukumar.Swaminathan@Sun.COM 	}
32710997SSukumar.Swaminathan@Sun.COM 
32810997SSukumar.Swaminathan@Sun.COM 	/* get the pci header image length */
32910997SSukumar.Swaminathan@Sun.COM 	pcih = (pci_header_t *)pciinfo;
33010997SSukumar.Swaminathan@Sun.COM 
33110997SSukumar.Swaminathan@Sun.COM 	doff = pcih->dataoffset[1];
33210997SSukumar.Swaminathan@Sun.COM 	doff <<= 8;
33310997SSukumar.Swaminathan@Sun.COM 	doff |= pcih->dataoffset[0];
33410997SSukumar.Swaminathan@Sun.COM 
33510997SSukumar.Swaminathan@Sun.COM 	/* some header section sanity check */
33610997SSukumar.Swaminathan@Sun.COM 	if (pcih->signature[0] != PCI_HEADER0 /* '55' */ ||
33710997SSukumar.Swaminathan@Sun.COM 	    pcih->signature[1] != PCI_HEADER1 /* 'AA' */ || doff > 50) {
33810997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) image format error: s0=%xh, s1=%xh,"
33910997SSukumar.Swaminathan@Sun.COM 		    "off=%xh\n", __func__, qlge->instance,
34010997SSukumar.Swaminathan@Sun.COM 		    pcih->signature[0], pcih->signature[1], doff);
34110997SSukumar.Swaminathan@Sun.COM 		return (STOP_SEARCH);
34210997SSukumar.Swaminathan@Sun.COM 	}
34310997SSukumar.Swaminathan@Sun.COM 
34410997SSukumar.Swaminathan@Sun.COM 	pcid = (pci_data_t *)(pciinfo + doff);
34510997SSukumar.Swaminathan@Sun.COM 
34610997SSukumar.Swaminathan@Sun.COM 	/* a slight sanity data section check */
34710997SSukumar.Swaminathan@Sun.COM 	if (pcid->signature[0] != 'P' || pcid->signature[1] != 'C' ||
34810997SSukumar.Swaminathan@Sun.COM 	    pcid->signature[2] != 'I' || pcid->signature[3] != 'R') {
34910997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) failed, data sig mismatch!",
35010997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance);
35110997SSukumar.Swaminathan@Sun.COM 		return (STOP_SEARCH);
35210997SSukumar.Swaminathan@Sun.COM 	}
35310997SSukumar.Swaminathan@Sun.COM 	image_size =
35410997SSukumar.Swaminathan@Sun.COM 	    (pcid->imagelength[0] | (pcid->imagelength[1] << 8))*
35510997SSukumar.Swaminathan@Sun.COM 	    PCI_SECTOR_SIZE /* 512 */;
35610997SSukumar.Swaminathan@Sun.COM 
35710997SSukumar.Swaminathan@Sun.COM 	switch (pcid->codetype) {
35810997SSukumar.Swaminathan@Sun.COM 	case PCI_CODE_X86PC:
35910997SSukumar.Swaminathan@Sun.COM 		QL_PRINT(DBG_FLASH, ("%s(%d) boot image is FTYPE_BIOS \n",
36010997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance));
36110997SSukumar.Swaminathan@Sun.COM 		break;
36210997SSukumar.Swaminathan@Sun.COM 	case PCI_CODE_FCODE:
36310997SSukumar.Swaminathan@Sun.COM 		QL_PRINT(DBG_FLASH, ("%s(%d) boot image is FTYPE_FCODE \n",
36410997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance));
36510997SSukumar.Swaminathan@Sun.COM 		break;
36610997SSukumar.Swaminathan@Sun.COM 	case PCI_CODE_EFI:
36710997SSukumar.Swaminathan@Sun.COM 		QL_PRINT(DBG_FLASH, ("%s(%d) boot image is FTYPE_EFI \n",
36810997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance));
36910997SSukumar.Swaminathan@Sun.COM 		break;
37010997SSukumar.Swaminathan@Sun.COM 	case PCI_CODE_HPPA:
37110997SSukumar.Swaminathan@Sun.COM 		QL_PRINT(DBG_FLASH, ("%s(%d) boot image is PCI_CODE_HPPA \n",
37210997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance));
37310997SSukumar.Swaminathan@Sun.COM 		break;
37410997SSukumar.Swaminathan@Sun.COM 	default:
37510997SSukumar.Swaminathan@Sun.COM 		QL_PRINT(DBG_FLASH, ("%s(%d) boot image is FTYPE_UNKNOWN \n",
37610997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance));
37710997SSukumar.Swaminathan@Sun.COM 		break;
37810997SSukumar.Swaminathan@Sun.COM 	}
37910997SSukumar.Swaminathan@Sun.COM 
38010997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("%s(%d) image size %x at %x\n",
38110997SSukumar.Swaminathan@Sun.COM 	    __func__, qlge->instance, image_size, *nextpos));
38210997SSukumar.Swaminathan@Sun.COM 
38310997SSukumar.Swaminathan@Sun.COM 	if (pcid->indicator == PCI_IND_LAST_IMAGE) {
38410997SSukumar.Swaminathan@Sun.COM 		QL_PRINT(DBG_FLASH, ("%s(%d) last boot image found \n",
38510997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance));
38610997SSukumar.Swaminathan@Sun.COM 		rval = LAST_IMAGE_FOUND;
38710997SSukumar.Swaminathan@Sun.COM 	} else {
38810997SSukumar.Swaminathan@Sun.COM 		rval = CONTINUE_SEARCH;
38910997SSukumar.Swaminathan@Sun.COM 	}
39010997SSukumar.Swaminathan@Sun.COM 	/* Get the next flash image address */
39110997SSukumar.Swaminathan@Sun.COM 	*nextpos += image_size;
39210997SSukumar.Swaminathan@Sun.COM 
39310997SSukumar.Swaminathan@Sun.COM 	return (rval);
39410997SSukumar.Swaminathan@Sun.COM }
39510997SSukumar.Swaminathan@Sun.COM 
39610997SSukumar.Swaminathan@Sun.COM /*
39710997SSukumar.Swaminathan@Sun.COM  * ql_find_flash_layout_table_data_structure
39810997SSukumar.Swaminathan@Sun.COM  * Find Flash Layout Table Data Structure (FLTDS) that
39910997SSukumar.Swaminathan@Sun.COM  * is located at the end of last boot image.
40010997SSukumar.Swaminathan@Sun.COM  * Assume FLTDS is located with first 2M bytes.
40110997SSukumar.Swaminathan@Sun.COM  * Note:
40210997SSukumar.Swaminathan@Sun.COM  * Driver must be in stalled state prior to entering or
40310997SSukumar.Swaminathan@Sun.COM  * add code to this function prior to calling ql_setup_flash()
40410997SSukumar.Swaminathan@Sun.COM  */
40510997SSukumar.Swaminathan@Sun.COM int
ql_find_flash_layout_table_data_structure_addr(qlge_t * qlge)40610997SSukumar.Swaminathan@Sun.COM ql_find_flash_layout_table_data_structure_addr(qlge_t *qlge)
40710997SSukumar.Swaminathan@Sun.COM {
40810997SSukumar.Swaminathan@Sun.COM 	int rval = DDI_FAILURE;
40910997SSukumar.Swaminathan@Sun.COM 	int result = CONTINUE_SEARCH;
41010997SSukumar.Swaminathan@Sun.COM 	uint32_t freadpos = 0;
41110997SSukumar.Swaminathan@Sun.COM 	uint8_t buf[FBUFSIZE];
41210997SSukumar.Swaminathan@Sun.COM 
41310997SSukumar.Swaminathan@Sun.COM 	if (qlge->flash_fltds_addr != 0) {
41410997SSukumar.Swaminathan@Sun.COM 		QL_PRINT(DBG_FLASH, ("%s(%d) done already\n",
41510997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance));
41610997SSukumar.Swaminathan@Sun.COM 		return (DDI_SUCCESS);
41710997SSukumar.Swaminathan@Sun.COM 	}
41810997SSukumar.Swaminathan@Sun.COM 	/*
41910997SSukumar.Swaminathan@Sun.COM 	 * Temporarily set the fdesc.flash_size to
42010997SSukumar.Swaminathan@Sun.COM 	 * 1M flash size to avoid failing of ql_dump_focde.
42110997SSukumar.Swaminathan@Sun.COM 	 */
42210997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.flash_size = FLASH_FIRMWARE_IMAGE_ADDR;
42310997SSukumar.Swaminathan@Sun.COM 
42410997SSukumar.Swaminathan@Sun.COM 	while (result == CONTINUE_SEARCH) {
42510997SSukumar.Swaminathan@Sun.COM 
42610997SSukumar.Swaminathan@Sun.COM 		if ((rval = qlge_dump_fcode(qlge, buf, FBUFSIZE, freadpos))
42710997SSukumar.Swaminathan@Sun.COM 		    != DDI_SUCCESS) {
42810997SSukumar.Swaminathan@Sun.COM 			cmn_err(CE_WARN, "%s(%d) qlge_dump_fcode failed"
42910997SSukumar.Swaminathan@Sun.COM 			    " pos=%xh rval=%xh",
43010997SSukumar.Swaminathan@Sun.COM 			    __func__, qlge->instance, freadpos, rval);
43110997SSukumar.Swaminathan@Sun.COM 			break;
43210997SSukumar.Swaminathan@Sun.COM 		}
43310997SSukumar.Swaminathan@Sun.COM 		/*
43410997SSukumar.Swaminathan@Sun.COM 		 * checkout the pci boot image format
43510997SSukumar.Swaminathan@Sun.COM 		 * and get next read address
43610997SSukumar.Swaminathan@Sun.COM 		 */
43710997SSukumar.Swaminathan@Sun.COM 		result = ql_check_pci(qlge, buf, &freadpos);
43810997SSukumar.Swaminathan@Sun.COM 		/*
43910997SSukumar.Swaminathan@Sun.COM 		 * find last image? If so, then the freadpos
44010997SSukumar.Swaminathan@Sun.COM 		 * is the address of FLTDS
44110997SSukumar.Swaminathan@Sun.COM 		 */
44210997SSukumar.Swaminathan@Sun.COM 		if (result == LAST_IMAGE_FOUND) {
44310997SSukumar.Swaminathan@Sun.COM 			QL_PRINT(DBG_FLASH,
44410997SSukumar.Swaminathan@Sun.COM 			    ("%s(%d) flash layout table data structure "
44510997SSukumar.Swaminathan@Sun.COM 			    "(FLTDS) address is at %x \n", __func__,
44610997SSukumar.Swaminathan@Sun.COM 			    qlge->instance, freadpos));
44710997SSukumar.Swaminathan@Sun.COM 			qlge->flash_fltds_addr = freadpos;
44810997SSukumar.Swaminathan@Sun.COM 			rval = DDI_SUCCESS;
44910997SSukumar.Swaminathan@Sun.COM 			break;
45010997SSukumar.Swaminathan@Sun.COM 		} else if (result == STOP_SEARCH) {
45110997SSukumar.Swaminathan@Sun.COM 			cmn_err(CE_WARN, "%s(%d) flash header incorrect,"
45210997SSukumar.Swaminathan@Sun.COM 			    "stop searching",
45310997SSukumar.Swaminathan@Sun.COM 			    __func__, qlge->instance);
45410997SSukumar.Swaminathan@Sun.COM 			break;
45510997SSukumar.Swaminathan@Sun.COM 		}
45610997SSukumar.Swaminathan@Sun.COM 	}
45710997SSukumar.Swaminathan@Sun.COM 	return (rval);
45810997SSukumar.Swaminathan@Sun.COM }
45910997SSukumar.Swaminathan@Sun.COM 
46010997SSukumar.Swaminathan@Sun.COM /*
46110997SSukumar.Swaminathan@Sun.COM  * ql_flash_fltds
46210997SSukumar.Swaminathan@Sun.COM  * Get flash layout table data structure table.
46310997SSukumar.Swaminathan@Sun.COM  */
46410997SSukumar.Swaminathan@Sun.COM static int
ql_flash_fltds(qlge_t * qlge)46510997SSukumar.Swaminathan@Sun.COM ql_flash_fltds(qlge_t *qlge)
46610997SSukumar.Swaminathan@Sun.COM {
46710997SSukumar.Swaminathan@Sun.COM 	uint32_t cnt;
46810997SSukumar.Swaminathan@Sun.COM 	uint16_t chksum, *bp, data;
46910997SSukumar.Swaminathan@Sun.COM 	int rval;
47010997SSukumar.Swaminathan@Sun.COM 
47110997SSukumar.Swaminathan@Sun.COM 	rval = qlge_dump_fcode(qlge, (uint8_t *)&qlge->fltds,
47210997SSukumar.Swaminathan@Sun.COM 	    sizeof (ql_fltds_t), qlge->flash_fltds_addr);
47310997SSukumar.Swaminathan@Sun.COM 	if (rval != DDI_SUCCESS) {
47410997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d)read error",
47510997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance);
47610997SSukumar.Swaminathan@Sun.COM 		bzero(&qlge->fltds, sizeof (ql_fltds_t));
47710997SSukumar.Swaminathan@Sun.COM 		return (rval);
47810997SSukumar.Swaminathan@Sun.COM 	}
47910997SSukumar.Swaminathan@Sun.COM 
48010997SSukumar.Swaminathan@Sun.COM 	QL_DUMP(DBG_FLASH, "flash layout table data structure:\n",
48110997SSukumar.Swaminathan@Sun.COM 	    &qlge->fltds, 8, sizeof (ql_fltds_t));
48210997SSukumar.Swaminathan@Sun.COM 
48310997SSukumar.Swaminathan@Sun.COM 	chksum = 0;
48410997SSukumar.Swaminathan@Sun.COM 	data = 0;
48510997SSukumar.Swaminathan@Sun.COM 	bp = (uint16_t *)&qlge->fltds;
48610997SSukumar.Swaminathan@Sun.COM 	for (cnt = 0; cnt < (sizeof (ql_fltds_t)) / 2; cnt++) {
48710997SSukumar.Swaminathan@Sun.COM 		data = *bp;
48810997SSukumar.Swaminathan@Sun.COM 		LITTLE_ENDIAN_16(&data);
48910997SSukumar.Swaminathan@Sun.COM 		chksum += data;
49010997SSukumar.Swaminathan@Sun.COM 		bp++;
49110997SSukumar.Swaminathan@Sun.COM 	}
49210997SSukumar.Swaminathan@Sun.COM 
49310997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_32(&qlge->fltds.signature);
49410997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->fltds.flt_addr_lo);
49510997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->fltds.flt_addr_hi);
49610997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->fltds.checksum);
49710997SSukumar.Swaminathan@Sun.COM 
49810997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("%s(%d) signature %xh\n",
49910997SSukumar.Swaminathan@Sun.COM 	    __func__, qlge->instance, qlge->fltds.signature));
50010997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("%s(%d) flt_addr_lo %xh\n",
50110997SSukumar.Swaminathan@Sun.COM 	    __func__, qlge->instance, qlge->fltds.flt_addr_lo));
50210997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("%s(%d) flt_addr_hi %xh\n",
50310997SSukumar.Swaminathan@Sun.COM 	    __func__, qlge->instance, qlge->fltds.flt_addr_hi));
50410997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("%s(%d) version %xh\n",
50510997SSukumar.Swaminathan@Sun.COM 	    __func__, qlge->instance, qlge->fltds.version));
50610997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("%s(%d) checksum %xh\n",
50710997SSukumar.Swaminathan@Sun.COM 	    __func__, qlge->instance, qlge->fltds.checksum));
50810997SSukumar.Swaminathan@Sun.COM 	/* QFLT */
50910997SSukumar.Swaminathan@Sun.COM 	if (chksum != 0 || qlge->fltds.signature != FLASH_FLTDS_SIGNATURE) {
51010997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) invalid flash layout table data"
51110997SSukumar.Swaminathan@Sun.COM 		    " structure", __func__, qlge->instance);
51210997SSukumar.Swaminathan@Sun.COM 		bzero(&qlge->fltds, sizeof (ql_fltds_t));
51310997SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
51410997SSukumar.Swaminathan@Sun.COM 	}
51510997SSukumar.Swaminathan@Sun.COM 	return (DDI_SUCCESS);
51610997SSukumar.Swaminathan@Sun.COM }
51710997SSukumar.Swaminathan@Sun.COM 
51810997SSukumar.Swaminathan@Sun.COM /*
51910997SSukumar.Swaminathan@Sun.COM  * ql_flash_flt
52010997SSukumar.Swaminathan@Sun.COM  * Get flash layout table.
52110997SSukumar.Swaminathan@Sun.COM  */
52210997SSukumar.Swaminathan@Sun.COM int
ql_flash_flt(qlge_t * qlge)52310997SSukumar.Swaminathan@Sun.COM ql_flash_flt(qlge_t *qlge)
52410997SSukumar.Swaminathan@Sun.COM {
52510997SSukumar.Swaminathan@Sun.COM 	uint32_t addr, cnt;
52610997SSukumar.Swaminathan@Sun.COM 	int rval = DDI_FAILURE;
52710997SSukumar.Swaminathan@Sun.COM 	ql_flt_entry_t *entry;
52810997SSukumar.Swaminathan@Sun.COM 	uint8_t region;
52910997SSukumar.Swaminathan@Sun.COM 
53010997SSukumar.Swaminathan@Sun.COM 	addr = qlge->fltds.flt_addr_hi;
53110997SSukumar.Swaminathan@Sun.COM 	addr <<= 16;
53210997SSukumar.Swaminathan@Sun.COM 	addr |= qlge->fltds.flt_addr_lo;
53310997SSukumar.Swaminathan@Sun.COM 
53410997SSukumar.Swaminathan@Sun.COM 	/* first read flt header to know how long the table is */
53510997SSukumar.Swaminathan@Sun.COM 	rval = qlge_dump_fcode(qlge, (uint8_t *)&qlge->flt.header,
53610997SSukumar.Swaminathan@Sun.COM 	    sizeof (ql_flt_header_t), addr);
53710997SSukumar.Swaminathan@Sun.COM 	if (rval != DDI_SUCCESS) {
53810997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) read flt header at %x error",
53910997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance, addr);
54010997SSukumar.Swaminathan@Sun.COM 		bzero(&qlge->flt, sizeof (ql_flt_header_t));
54110997SSukumar.Swaminathan@Sun.COM 		return (rval);
54210997SSukumar.Swaminathan@Sun.COM 	}
54310997SSukumar.Swaminathan@Sun.COM 
54410997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->flt.header.version);
54510997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->flt.header.length);
54610997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->flt.header.checksum);
54710997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->flt.header.reserved);
54810997SSukumar.Swaminathan@Sun.COM 
54910997SSukumar.Swaminathan@Sun.COM 	if ((qlge->flt.header.version != 1) &&
55010997SSukumar.Swaminathan@Sun.COM 	    (qlge->flt.header.version != 0)) {
551*12073SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) flt header version %x unsupported",
552*12073SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance, qlge->flt.header.version);
55310997SSukumar.Swaminathan@Sun.COM 		bzero(&qlge->flt, sizeof (ql_flt_header_t));
55410997SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
55510997SSukumar.Swaminathan@Sun.COM 	}
55610997SSukumar.Swaminathan@Sun.COM 	/* 2.allocate memory to save all flt table entries */
55710997SSukumar.Swaminathan@Sun.COM 	if ((qlge->flt.ql_flt_entry_ptr = (ql_flt_entry_t *)
55810997SSukumar.Swaminathan@Sun.COM 	    (kmem_zalloc(qlge->flt.header.length, KM_SLEEP))) == NULL) {
55910997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) flt table alloc failed",
56010997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance);
56110997SSukumar.Swaminathan@Sun.COM 		goto err;
56210997SSukumar.Swaminathan@Sun.COM 	}
56310997SSukumar.Swaminathan@Sun.COM 	/* how many tables? */
56410997SSukumar.Swaminathan@Sun.COM 	qlge->flt.num_entries = (uint16_t)(qlge->flt.header.length /
56510997SSukumar.Swaminathan@Sun.COM 	    sizeof (ql_flt_entry_t));
56610997SSukumar.Swaminathan@Sun.COM 
56710997SSukumar.Swaminathan@Sun.COM 	/* 3. read the rest of flt table */
56810997SSukumar.Swaminathan@Sun.COM 	addr += (uint32_t)sizeof (ql_flt_header_t);
56910997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("%s(%d) flt has %x entries \n",
57010997SSukumar.Swaminathan@Sun.COM 	    __func__, qlge->instance, qlge->flt.num_entries));
57110997SSukumar.Swaminathan@Sun.COM 	rval = qlge_dump_fcode(qlge,
57210997SSukumar.Swaminathan@Sun.COM 	    (uint8_t *)qlge->flt.ql_flt_entry_ptr, qlge->flt.header.length,
57310997SSukumar.Swaminathan@Sun.COM 	    addr);
57410997SSukumar.Swaminathan@Sun.COM 	if (rval != DDI_SUCCESS) {
57510997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "read flt table entry error");
57610997SSukumar.Swaminathan@Sun.COM 		goto err;
57710997SSukumar.Swaminathan@Sun.COM 	}
57810997SSukumar.Swaminathan@Sun.COM 
57910997SSukumar.Swaminathan@Sun.COM 	entry = (ql_flt_entry_t *)qlge->flt.ql_flt_entry_ptr;
58010997SSukumar.Swaminathan@Sun.COM 	for (cnt = 0; cnt < qlge->flt.num_entries; cnt++) {
58110997SSukumar.Swaminathan@Sun.COM 		LITTLE_ENDIAN_32(&entry->size);
58210997SSukumar.Swaminathan@Sun.COM 		LITTLE_ENDIAN_32(&entry->begin_addr);
58310997SSukumar.Swaminathan@Sun.COM 		LITTLE_ENDIAN_32(&entry->end_addr);
58410997SSukumar.Swaminathan@Sun.COM 		entry++;
58510997SSukumar.Swaminathan@Sun.COM 	}
58610997SSukumar.Swaminathan@Sun.COM 	/* TO Do :4. Checksum verification */
58710997SSukumar.Swaminathan@Sun.COM 
58810997SSukumar.Swaminathan@Sun.COM 	/* 5.search index of Flash Descriptor Table in the Flash Layout Table */
58910997SSukumar.Swaminathan@Sun.COM 	entry = (ql_flt_entry_t *)qlge->flt.ql_flt_entry_ptr;
59010997SSukumar.Swaminathan@Sun.COM 	qlge->flash_fdt_addr = 0;
59110997SSukumar.Swaminathan@Sun.COM 	for (cnt = 0; cnt < qlge->flt.num_entries; cnt++) {
59210997SSukumar.Swaminathan@Sun.COM 		if (entry->region == FLT_REGION_FDT) {
59310997SSukumar.Swaminathan@Sun.COM 			qlge->flash_flt_fdt_index = cnt;
59410997SSukumar.Swaminathan@Sun.COM 			qlge->flash_fdt_addr = entry->begin_addr;
59510997SSukumar.Swaminathan@Sun.COM 			qlge->flash_fdt_size = entry->size;
59610997SSukumar.Swaminathan@Sun.COM 			QL_PRINT(DBG_FLASH, ("%s(%d) flash_flt_fdt_index is"
59710997SSukumar.Swaminathan@Sun.COM 			    " %x, addr %x,size %x \n", __func__,
59810997SSukumar.Swaminathan@Sun.COM 			    qlge->instance,
59910997SSukumar.Swaminathan@Sun.COM 			    cnt, entry->begin_addr, entry->size));
60010997SSukumar.Swaminathan@Sun.COM 			break;
60110997SSukumar.Swaminathan@Sun.COM 		}
60210997SSukumar.Swaminathan@Sun.COM 		entry++;
60310997SSukumar.Swaminathan@Sun.COM 	}
60410997SSukumar.Swaminathan@Sun.COM 
60510997SSukumar.Swaminathan@Sun.COM 	if (qlge->flash_fdt_addr == 0) {
60610997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) flash descriptor table not found",
60710997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance);
60810997SSukumar.Swaminathan@Sun.COM 		goto err;
60910997SSukumar.Swaminathan@Sun.COM 	}
61010997SSukumar.Swaminathan@Sun.COM 	/* 6.search index of Nic Config. Table in the Flash Layout Table */
61110997SSukumar.Swaminathan@Sun.COM 	entry = (ql_flt_entry_t *)qlge->flt.ql_flt_entry_ptr;
61210997SSukumar.Swaminathan@Sun.COM 	if (qlge->func_number == qlge->fn0_net)
61310997SSukumar.Swaminathan@Sun.COM 		region = FLT_REGION_NIC_PARAM0;
61410997SSukumar.Swaminathan@Sun.COM 	else
61510997SSukumar.Swaminathan@Sun.COM 		region = FLT_REGION_NIC_PARAM1;
61610997SSukumar.Swaminathan@Sun.COM 	qlge->flash_nic_config_table_addr = 0;
61710997SSukumar.Swaminathan@Sun.COM 	for (cnt = 0; cnt < qlge->flt.num_entries; cnt++) {
61810997SSukumar.Swaminathan@Sun.COM 		if (entry->region == region) {
61910997SSukumar.Swaminathan@Sun.COM 			qlge->flash_flt_nic_config_table_index = cnt;
62010997SSukumar.Swaminathan@Sun.COM 			qlge->flash_nic_config_table_addr = entry->begin_addr;
62110997SSukumar.Swaminathan@Sun.COM 			qlge->flash_nic_config_table_size = entry->size;
62210997SSukumar.Swaminathan@Sun.COM 			QL_PRINT(DBG_FLASH, ("%s(%d) "
62310997SSukumar.Swaminathan@Sun.COM 			    "flash_flt_nic_config_table_index "
62410997SSukumar.Swaminathan@Sun.COM 			    "is %x, address %x, size %x \n",
62510997SSukumar.Swaminathan@Sun.COM 			    __func__, qlge->instance,
62610997SSukumar.Swaminathan@Sun.COM 			    cnt, entry->begin_addr, entry->size));
62710997SSukumar.Swaminathan@Sun.COM 			break;
62810997SSukumar.Swaminathan@Sun.COM 		}
62910997SSukumar.Swaminathan@Sun.COM 		entry++;
63010997SSukumar.Swaminathan@Sun.COM 	}
63110997SSukumar.Swaminathan@Sun.COM 	if (qlge->flash_nic_config_table_addr == 0) {
63210997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) NIC Configuration Table not found",
63310997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance);
63410997SSukumar.Swaminathan@Sun.COM 		goto err;
63510997SSukumar.Swaminathan@Sun.COM 	}
63610997SSukumar.Swaminathan@Sun.COM 
63710997SSukumar.Swaminathan@Sun.COM 	return (DDI_SUCCESS);
63810997SSukumar.Swaminathan@Sun.COM err:
63910997SSukumar.Swaminathan@Sun.COM 	bzero(&qlge->flt, sizeof (ql_flt_header_t));
64010997SSukumar.Swaminathan@Sun.COM 	if (qlge->flt.ql_flt_entry_ptr != NULL) {
64110997SSukumar.Swaminathan@Sun.COM 		bzero(&qlge->flt.ql_flt_entry_ptr, qlge->flt.header.length);
64210997SSukumar.Swaminathan@Sun.COM 		kmem_free(qlge->flt.ql_flt_entry_ptr, qlge->flt.header.length);
64310997SSukumar.Swaminathan@Sun.COM 		qlge->flt.ql_flt_entry_ptr = NULL;
64410997SSukumar.Swaminathan@Sun.COM 	}
64510997SSukumar.Swaminathan@Sun.COM 	cmn_err(CE_WARN, "%s(%d) read FLT failed", __func__, qlge->instance);
64610997SSukumar.Swaminathan@Sun.COM 	return (DDI_FAILURE);
64710997SSukumar.Swaminathan@Sun.COM }
64810997SSukumar.Swaminathan@Sun.COM 
64910997SSukumar.Swaminathan@Sun.COM /*
65010997SSukumar.Swaminathan@Sun.COM  * ql_flash_desc
65110997SSukumar.Swaminathan@Sun.COM  * Get flash descriptor table.
65210997SSukumar.Swaminathan@Sun.COM  */
65310997SSukumar.Swaminathan@Sun.COM static int
ql_flash_desc(qlge_t * qlge)65410997SSukumar.Swaminathan@Sun.COM ql_flash_desc(qlge_t *qlge)
65510997SSukumar.Swaminathan@Sun.COM {
65610997SSukumar.Swaminathan@Sun.COM 	uint8_t w8;
65710997SSukumar.Swaminathan@Sun.COM 	uint32_t cnt, addr;
65810997SSukumar.Swaminathan@Sun.COM 	uint16_t chksum, *bp, data;
65910997SSukumar.Swaminathan@Sun.COM 	int rval;
66010997SSukumar.Swaminathan@Sun.COM 
66110997SSukumar.Swaminathan@Sun.COM 	addr = qlge->flash_fdt_addr;
66210997SSukumar.Swaminathan@Sun.COM 
66310997SSukumar.Swaminathan@Sun.COM 	rval = qlge_dump_fcode(qlge, (uint8_t *)&qlge->fdesc,
66410997SSukumar.Swaminathan@Sun.COM 	    sizeof (flash_desc_t), addr);
66510997SSukumar.Swaminathan@Sun.COM 	if (rval != DDI_SUCCESS) {
66610997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) read Flash Descriptor Table error",
66710997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance);
66810997SSukumar.Swaminathan@Sun.COM 		bzero(&qlge->fdesc, sizeof (flash_desc_t));
66910997SSukumar.Swaminathan@Sun.COM 		return (rval);
67010997SSukumar.Swaminathan@Sun.COM 	}
67110997SSukumar.Swaminathan@Sun.COM 
67210997SSukumar.Swaminathan@Sun.COM 	chksum = 0;
67310997SSukumar.Swaminathan@Sun.COM 	data = 0;
67410997SSukumar.Swaminathan@Sun.COM 	bp = (uint16_t *)&qlge->fdesc;
67510997SSukumar.Swaminathan@Sun.COM 	for (cnt = 0; cnt < (sizeof (flash_desc_t)) / 2; cnt++) {
67610997SSukumar.Swaminathan@Sun.COM 		data = *bp;
67710997SSukumar.Swaminathan@Sun.COM 		LITTLE_ENDIAN_16(&data);
67810997SSukumar.Swaminathan@Sun.COM 		chksum += data;
67910997SSukumar.Swaminathan@Sun.COM 		bp++;
68010997SSukumar.Swaminathan@Sun.COM 	}
68110997SSukumar.Swaminathan@Sun.COM 	/* endian adjustment */
68210997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_32(&qlge->fdesc.flash_valid);
68310997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->fdesc.flash_version);
68410997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->fdesc.flash_len);
68510997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->fdesc.flash_checksum);
68610997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->fdesc.flash_unused);
68710997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->fdesc.flash_manuf);
68810997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->fdesc.flash_id);
68910997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_32(&qlge->fdesc.block_size);
69010997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_32(&qlge->fdesc.alt_block_size);
69110997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_32(&qlge->fdesc.flash_size);
69210997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_32(&qlge->fdesc.write_enable_data);
69310997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_32(&qlge->fdesc.read_timeout);
69410997SSukumar.Swaminathan@Sun.COM 
69510997SSukumar.Swaminathan@Sun.COM 	/* flash size in desc table is in 1024 bytes */
69610997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("flash_valid=%xh\n", qlge->fdesc.flash_valid));
69710997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("flash_version=%xh\n", qlge->fdesc.flash_version));
69810997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("flash_len=%xh\n", qlge->fdesc.flash_len));
69910997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("flash_checksum=%xh\n",
70010997SSukumar.Swaminathan@Sun.COM 	    qlge->fdesc.flash_checksum));
70110997SSukumar.Swaminathan@Sun.COM 
70210997SSukumar.Swaminathan@Sun.COM 	w8 = qlge->fdesc.flash_model[15];
70310997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.flash_model[15] = 0;
70410997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("flash_model=%s\n", qlge->fdesc.flash_model));
70510997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.flash_model[15] = w8;
70610997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("flash_size=%xK bytes\n", qlge->fdesc.flash_size));
70710997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.flash_size = qlge->fdesc.flash_size * 0x400;
70810997SSukumar.Swaminathan@Sun.COM 	qlge->flash_info.flash_size = qlge->fdesc.flash_size;
70910997SSukumar.Swaminathan@Sun.COM 
71010997SSukumar.Swaminathan@Sun.COM 	if (chksum != 0 || qlge->fdesc.flash_valid != FLASH_DESC_VAILD ||
71110997SSukumar.Swaminathan@Sun.COM 	    qlge->fdesc.flash_version != FLASH_DESC_VERSION) {
71210997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "invalid descriptor table");
71310997SSukumar.Swaminathan@Sun.COM 		bzero(&qlge->fdesc, sizeof (flash_desc_t));
71410997SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
71510997SSukumar.Swaminathan@Sun.COM 	}
71610997SSukumar.Swaminathan@Sun.COM 
71710997SSukumar.Swaminathan@Sun.COM 	return (DDI_SUCCESS);
71810997SSukumar.Swaminathan@Sun.COM }
71910997SSukumar.Swaminathan@Sun.COM 
72010997SSukumar.Swaminathan@Sun.COM /*
72110997SSukumar.Swaminathan@Sun.COM  * ql_flash_nic_config
72210997SSukumar.Swaminathan@Sun.COM  * Get flash NIC Configuration table.
72310997SSukumar.Swaminathan@Sun.COM  */
72410997SSukumar.Swaminathan@Sun.COM static int
ql_flash_nic_config(qlge_t * qlge)72510997SSukumar.Swaminathan@Sun.COM ql_flash_nic_config(qlge_t *qlge)
72610997SSukumar.Swaminathan@Sun.COM {
72710997SSukumar.Swaminathan@Sun.COM 	uint32_t cnt, addr;
72810997SSukumar.Swaminathan@Sun.COM 	uint16_t chksum, *bp, data;
72910997SSukumar.Swaminathan@Sun.COM 	int rval;
73010997SSukumar.Swaminathan@Sun.COM 
73110997SSukumar.Swaminathan@Sun.COM 	addr = qlge->flash_nic_config_table_addr;
73210997SSukumar.Swaminathan@Sun.COM 
73310997SSukumar.Swaminathan@Sun.COM 	rval = qlge_dump_fcode(qlge, (uint8_t *)&qlge->nic_config,
73410997SSukumar.Swaminathan@Sun.COM 	    sizeof (ql_nic_config_t), addr);
73510997SSukumar.Swaminathan@Sun.COM 
73610997SSukumar.Swaminathan@Sun.COM 	if (rval != DDI_SUCCESS) {
73710997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "fail to read nic_cfg image %xh", rval);
73810997SSukumar.Swaminathan@Sun.COM 		bzero(&qlge->nic_config, sizeof (ql_nic_config_t));
73910997SSukumar.Swaminathan@Sun.COM 		return (rval);
74010997SSukumar.Swaminathan@Sun.COM 	}
74110997SSukumar.Swaminathan@Sun.COM 
74210997SSukumar.Swaminathan@Sun.COM 	chksum = 0;
74310997SSukumar.Swaminathan@Sun.COM 	data = 0;
74410997SSukumar.Swaminathan@Sun.COM 	bp = (uint16_t *)&qlge->nic_config;
74510997SSukumar.Swaminathan@Sun.COM 	for (cnt = 0; cnt < (sizeof (ql_nic_config_t)) / 2; cnt++) {
74610997SSukumar.Swaminathan@Sun.COM 		data = *bp;
74710997SSukumar.Swaminathan@Sun.COM 		LITTLE_ENDIAN_16(&data);
74810997SSukumar.Swaminathan@Sun.COM 		chksum += data;
74910997SSukumar.Swaminathan@Sun.COM 		bp++;
75010997SSukumar.Swaminathan@Sun.COM 	}
75110997SSukumar.Swaminathan@Sun.COM 
75210997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_32(&qlge->nic_config.signature);
75310997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->nic_config.version);
75410997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->nic_config.size);
75510997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->nic_config.checksum);
75610997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->nic_config.total_data_size);
75710997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->nic_config.num_of_entries);
75810997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->nic_config.vlan_id);
75910997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->nic_config.last_entry);
76010997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->nic_config.subsys_vendor_id);
76110997SSukumar.Swaminathan@Sun.COM 	LITTLE_ENDIAN_16(&qlge->nic_config.subsys_device_id);
76210997SSukumar.Swaminathan@Sun.COM 
76310997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): signature=%xh\n",
76410997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.signature));
76510997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): size=%xh\n",
76610997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.size));
76710997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): checksum=%xh\n",
76810997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.checksum));
76910997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): version=%xh\n",
77010997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.version));
77110997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): total_data_size=%xh\n",
77210997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.total_data_size));
77310997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): num_of_entries=%xh\n",
77410997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.num_of_entries));
77510997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): data_type=%xh\n",
77610997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.factory_data_type));
77710997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): data_type_size=%xh\n",
77810997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.factory_data_type_size));
77910997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH,
78010997SSukumar.Swaminathan@Sun.COM 	    ("(%d): factory mac=%02x %02x %02x %02x %02x %02x h\n",
78110997SSukumar.Swaminathan@Sun.COM 	    qlge->instance,
78210997SSukumar.Swaminathan@Sun.COM 	    qlge->nic_config.factory_MAC[0],
78310997SSukumar.Swaminathan@Sun.COM 	    qlge->nic_config.factory_MAC[1],
78410997SSukumar.Swaminathan@Sun.COM 	    qlge->nic_config.factory_MAC[2],
78510997SSukumar.Swaminathan@Sun.COM 	    qlge->nic_config.factory_MAC[3],
78610997SSukumar.Swaminathan@Sun.COM 	    qlge->nic_config.factory_MAC[4],
78710997SSukumar.Swaminathan@Sun.COM 	    qlge->nic_config.factory_MAC[5]));
78810997SSukumar.Swaminathan@Sun.COM 
78910997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): data_type=%xh\n",
79010997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.clp_data_type));
79110997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): data_type_size=%xh\n",
79210997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.clp_data_type_size));
79310997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): clp mac=%x %x %x %x %x %x h\n",
79410997SSukumar.Swaminathan@Sun.COM 	    qlge->instance,
79510997SSukumar.Swaminathan@Sun.COM 	    qlge->nic_config.clp_MAC[0],
79610997SSukumar.Swaminathan@Sun.COM 	    qlge->nic_config.clp_MAC[1],
79710997SSukumar.Swaminathan@Sun.COM 	    qlge->nic_config.clp_MAC[2],
79810997SSukumar.Swaminathan@Sun.COM 	    qlge->nic_config.clp_MAC[3],
79910997SSukumar.Swaminathan@Sun.COM 	    qlge->nic_config.clp_MAC[4],
80010997SSukumar.Swaminathan@Sun.COM 	    qlge->nic_config.clp_MAC[5]));
80110997SSukumar.Swaminathan@Sun.COM 
80210997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): data_type=%xh\n",
80310997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.clp_vlan_data_type));
80410997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): data_type_size=%xh\n",
80510997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.clp_vlan_data_type_size));
80610997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): vlan_id=%xh\n",
80710997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.vlan_id));
80810997SSukumar.Swaminathan@Sun.COM 
80910997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): data_type=%xh\n",
81010997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.last_data_type));
81110997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): data_type_size=%xh\n",
81210997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.last_data_type_size));
81310997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): last_entry=%xh\n",
81410997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.last_entry));
81510997SSukumar.Swaminathan@Sun.COM 
81610997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): subsys_vendor_id=%xh\n",
81710997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.subsys_vendor_id));
81810997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("(%d): subsys_device_id=%xh\n",
81910997SSukumar.Swaminathan@Sun.COM 	    qlge->instance, qlge->nic_config.subsys_device_id));
82010997SSukumar.Swaminathan@Sun.COM 
82110997SSukumar.Swaminathan@Sun.COM 	if (chksum != 0 || qlge->nic_config.signature !=
82210997SSukumar.Swaminathan@Sun.COM 	    FLASH_NIC_CONFIG_SIGNATURE || qlge->nic_config.version != 1) {
82310997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN,
82410997SSukumar.Swaminathan@Sun.COM 		    "invalid flash nic configuration table: chksum %x, "
82510997SSukumar.Swaminathan@Sun.COM 		    "signature %x, version %x",
82610997SSukumar.Swaminathan@Sun.COM 		    chksum, qlge->nic_config.signature,
82710997SSukumar.Swaminathan@Sun.COM 		    qlge->nic_config.version);
82810997SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
82910997SSukumar.Swaminathan@Sun.COM 	}
83010997SSukumar.Swaminathan@Sun.COM 
83110997SSukumar.Swaminathan@Sun.COM 	return (DDI_SUCCESS);
83210997SSukumar.Swaminathan@Sun.COM }
83310997SSukumar.Swaminathan@Sun.COM 
83410997SSukumar.Swaminathan@Sun.COM int
ql_flash_vpd(qlge_t * qlge,uint8_t * buf)83510997SSukumar.Swaminathan@Sun.COM ql_flash_vpd(qlge_t *qlge, uint8_t *buf)
83610997SSukumar.Swaminathan@Sun.COM {
83710997SSukumar.Swaminathan@Sun.COM 	uint32_t cnt;
83810997SSukumar.Swaminathan@Sun.COM 	uint16_t chksum, *bp, data;
83910997SSukumar.Swaminathan@Sun.COM 	int rval;
84010997SSukumar.Swaminathan@Sun.COM 	uint32_t vpd_size;
84110997SSukumar.Swaminathan@Sun.COM 
84210997SSukumar.Swaminathan@Sun.COM 	if (buf == NULL) {
84310997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) buffer is not available.",
84410997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance);
84510997SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
84610997SSukumar.Swaminathan@Sun.COM 	}
84710997SSukumar.Swaminathan@Sun.COM 
84810997SSukumar.Swaminathan@Sun.COM 	if (!qlge->flash_vpd_addr) {
84910997SSukumar.Swaminathan@Sun.COM 		if (qlge->func_number == qlge->fn0_net)
85010997SSukumar.Swaminathan@Sun.COM 			qlge->flash_vpd_addr = ISP_8100_VPD0_ADDR;
85110997SSukumar.Swaminathan@Sun.COM 		else
85210997SSukumar.Swaminathan@Sun.COM 			qlge->flash_vpd_addr = ISP_8100_VPD1_ADDR;
85310997SSukumar.Swaminathan@Sun.COM 		vpd_size = ISP_8100_VPD0_SIZE;
85410997SSukumar.Swaminathan@Sun.COM 	}
85510997SSukumar.Swaminathan@Sun.COM 	rval = qlge_dump_fcode(qlge, buf, vpd_size, qlge->flash_vpd_addr);
85610997SSukumar.Swaminathan@Sun.COM 
85710997SSukumar.Swaminathan@Sun.COM 	if (rval != DDI_SUCCESS) {
85810997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d)read error",
85910997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance);
86010997SSukumar.Swaminathan@Sun.COM 		bzero(buf, vpd_size);
86110997SSukumar.Swaminathan@Sun.COM 		return (rval);
86210997SSukumar.Swaminathan@Sun.COM 	}
86310997SSukumar.Swaminathan@Sun.COM 
86410997SSukumar.Swaminathan@Sun.COM 	QL_DUMP(DBG_FLASH, "flash vpd table raw data:\n", buf, 8, vpd_size);
86510997SSukumar.Swaminathan@Sun.COM 
86610997SSukumar.Swaminathan@Sun.COM 	chksum = 0;
86710997SSukumar.Swaminathan@Sun.COM 	data = 0;
86810997SSukumar.Swaminathan@Sun.COM 	bp = (uint16_t *)(void *)buf;
86910997SSukumar.Swaminathan@Sun.COM 	for (cnt = 0; cnt < (vpd_size/2); cnt++) {
87010997SSukumar.Swaminathan@Sun.COM 		data = *bp;
87110997SSukumar.Swaminathan@Sun.COM 		LITTLE_ENDIAN_16(&data);
87210997SSukumar.Swaminathan@Sun.COM 		chksum += data;
87310997SSukumar.Swaminathan@Sun.COM 		bp++;
87410997SSukumar.Swaminathan@Sun.COM 	}
87510997SSukumar.Swaminathan@Sun.COM 	if (chksum != 0) {
87610997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "%s(%d) invalid flash vpd table",
87710997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance);
87810997SSukumar.Swaminathan@Sun.COM 		return (DDI_FAILURE);
87910997SSukumar.Swaminathan@Sun.COM 	}
88010997SSukumar.Swaminathan@Sun.COM 	return (DDI_SUCCESS);
88110997SSukumar.Swaminathan@Sun.COM }
88210997SSukumar.Swaminathan@Sun.COM 
88310997SSukumar.Swaminathan@Sun.COM int
ql_get_flash_params(qlge_t * qlge)88410997SSukumar.Swaminathan@Sun.COM ql_get_flash_params(qlge_t *qlge)
88510997SSukumar.Swaminathan@Sun.COM {
88610997SSukumar.Swaminathan@Sun.COM 	int rval = DDI_SUCCESS;
88710997SSukumar.Swaminathan@Sun.COM 
88810997SSukumar.Swaminathan@Sun.COM 	/* Get semaphore to access Flash Address and Flash Data Registers */
88910997SSukumar.Swaminathan@Sun.COM 	if (ql_sem_spinlock(qlge, QL_FLASH_SEM_MASK)) {
89010997SSukumar.Swaminathan@Sun.COM 		rval = DDI_FAILURE;
89110997SSukumar.Swaminathan@Sun.COM 		goto out;
89210997SSukumar.Swaminathan@Sun.COM 	}
89310997SSukumar.Swaminathan@Sun.COM 	/* do test read of flash ID */
89410997SSukumar.Swaminathan@Sun.COM 	rval = ql_flash_id(qlge);
89510997SSukumar.Swaminathan@Sun.COM 	if (rval != DDI_SUCCESS)
89610997SSukumar.Swaminathan@Sun.COM 		goto out;
89710997SSukumar.Swaminathan@Sun.COM 
89810997SSukumar.Swaminathan@Sun.COM 	/*
89910997SSukumar.Swaminathan@Sun.COM 	 * Temporarily set the fdesc.flash_size to
90010997SSukumar.Swaminathan@Sun.COM 	 * 4M flash size to avoid failing of ql_dump_focde.
90110997SSukumar.Swaminathan@Sun.COM 	 */
90210997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.flash_size = 4096 * 1024; /* ie. 4M bytes */
90310997SSukumar.Swaminathan@Sun.COM 
90410997SSukumar.Swaminathan@Sun.COM 	/* Default flash descriptor table. */
90510997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.write_statusreg_cmd = 1;
90610997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.write_enable_bits = 0;
90710997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.unprotect_sector_cmd = 0;
90810997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.protect_sector_cmd = 0;
90910997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.write_disable_bits = 0x9c;
91010997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.block_size = 0x10000;
91110997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.erase_cmd = 0xd8;
91210997SSukumar.Swaminathan@Sun.COM 
91310997SSukumar.Swaminathan@Sun.COM 	/* ! todo : should read from fltds! */
91410997SSukumar.Swaminathan@Sun.COM 	/* !ql_get_flash_params(qlge); */
91510997SSukumar.Swaminathan@Sun.COM 	qlge->fltds.flt_addr_hi = 0x36;
91610997SSukumar.Swaminathan@Sun.COM 	qlge->fltds.flt_addr_lo = 0x1000;
91710997SSukumar.Swaminathan@Sun.COM 	/* read all other tables from Flash memory */
91810997SSukumar.Swaminathan@Sun.COM 	if (ql_flash_flt(qlge) != DDI_SUCCESS) {
91910997SSukumar.Swaminathan@Sun.COM 		if (CFG_IST(qlge, CFG_CHIP_8100)) {
92010997SSukumar.Swaminathan@Sun.COM 			qlge->flash_fdt_addr = ISP_8100_FDT_ADDR; /* 0x360000 */
92110997SSukumar.Swaminathan@Sun.COM 			if (qlge->func_number == qlge->fn0_net)
92210997SSukumar.Swaminathan@Sun.COM 				/* 0x140200 */
92310997SSukumar.Swaminathan@Sun.COM 				qlge->flash_nic_config_table_addr =
92410997SSukumar.Swaminathan@Sun.COM 				    ISP_8100_NIC_PARAM0_ADDR;
92510997SSukumar.Swaminathan@Sun.COM 			else
92610997SSukumar.Swaminathan@Sun.COM 				/* 0x140600 */
92710997SSukumar.Swaminathan@Sun.COM 				qlge->flash_nic_config_table_addr =
92810997SSukumar.Swaminathan@Sun.COM 				    ISP_8100_NIC_PARAM1_ADDR;
92910997SSukumar.Swaminathan@Sun.COM 		}
93010997SSukumar.Swaminathan@Sun.COM 	}
93111016SSukumar.Swaminathan@Sun.COM 	(void) ql_flash_desc(qlge);
93211016SSukumar.Swaminathan@Sun.COM 	(void) ql_flash_nic_config(qlge);
93310997SSukumar.Swaminathan@Sun.COM 
93410997SSukumar.Swaminathan@Sun.COM out:
93510997SSukumar.Swaminathan@Sun.COM 	ql_sem_unlock(qlge, QL_FLASH_SEM_MASK);
93610997SSukumar.Swaminathan@Sun.COM 
93710997SSukumar.Swaminathan@Sun.COM 	return (rval);
93810997SSukumar.Swaminathan@Sun.COM }
93910997SSukumar.Swaminathan@Sun.COM 
94010997SSukumar.Swaminathan@Sun.COM /*
94110997SSukumar.Swaminathan@Sun.COM  * ql_setup_flash
94210997SSukumar.Swaminathan@Sun.COM  * Gets the manufacturer and id number of the flash chip,
94310997SSukumar.Swaminathan@Sun.COM  * and sets up the size parameter.
94410997SSukumar.Swaminathan@Sun.COM  */
94510997SSukumar.Swaminathan@Sun.COM int
ql_setup_flash(qlge_t * qlge)94610997SSukumar.Swaminathan@Sun.COM ql_setup_flash(qlge_t *qlge)
94710997SSukumar.Swaminathan@Sun.COM {
94810997SSukumar.Swaminathan@Sun.COM 	int rval = DDI_SUCCESS;
94910997SSukumar.Swaminathan@Sun.COM 
95010997SSukumar.Swaminathan@Sun.COM 	if (qlge->flash_fltds_addr != 0) {
95110997SSukumar.Swaminathan@Sun.COM 		return (rval);
95210997SSukumar.Swaminathan@Sun.COM 	}
95310997SSukumar.Swaminathan@Sun.COM 	if (ql_sem_spinlock(qlge, QL_FLASH_SEM_MASK)) {
95410997SSukumar.Swaminathan@Sun.COM 		rval = DDI_FAILURE;
95510997SSukumar.Swaminathan@Sun.COM 		goto out;
95610997SSukumar.Swaminathan@Sun.COM 	}
95710997SSukumar.Swaminathan@Sun.COM 	/* try reading flash ID */
95810997SSukumar.Swaminathan@Sun.COM 	rval = ql_flash_id(qlge);
95910997SSukumar.Swaminathan@Sun.COM 	if (rval != DDI_SUCCESS)
96010997SSukumar.Swaminathan@Sun.COM 		goto out;
96110997SSukumar.Swaminathan@Sun.COM 
96210997SSukumar.Swaminathan@Sun.COM 	/* Default flash descriptor table. */
96310997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.write_statusreg_cmd = 1;
96410997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.write_enable_bits = 0;
96510997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.unprotect_sector_cmd = 0;
96610997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.protect_sector_cmd = 0;
96710997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.write_disable_bits = 0x9c;
96810997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.block_size = 0x10000;
96910997SSukumar.Swaminathan@Sun.COM 	qlge->fdesc.erase_cmd = 0xd8;
97010997SSukumar.Swaminathan@Sun.COM 	/* 1 Get the location of Flash Layout Table Data Structure (FLTDS) */
97110997SSukumar.Swaminathan@Sun.COM 	if (ql_find_flash_layout_table_data_structure_addr(qlge)
97210997SSukumar.Swaminathan@Sun.COM 	    == DDI_SUCCESS) {
97310997SSukumar.Swaminathan@Sun.COM 		/* 2,read fltds */
97410997SSukumar.Swaminathan@Sun.COM 		if (ql_flash_fltds(qlge) == DDI_SUCCESS) {
97510997SSukumar.Swaminathan@Sun.COM 			/*
97610997SSukumar.Swaminathan@Sun.COM 			 * 3,search for flash descriptor table (FDT)
97710997SSukumar.Swaminathan@Sun.COM 			 * and Nic Configuration Table indices
97810997SSukumar.Swaminathan@Sun.COM 			 */
97910997SSukumar.Swaminathan@Sun.COM 			if ((qlge->flash_fdt_addr == 0) ||
98010997SSukumar.Swaminathan@Sun.COM 			    (qlge->flash_nic_config_table_addr == 0)) {
98110997SSukumar.Swaminathan@Sun.COM 				rval = ql_flash_flt(qlge);
98210997SSukumar.Swaminathan@Sun.COM 				if (rval == DDI_SUCCESS) {
98311016SSukumar.Swaminathan@Sun.COM 					(void) ql_flash_desc(qlge);
98411016SSukumar.Swaminathan@Sun.COM 					(void) ql_flash_nic_config(qlge);
98510997SSukumar.Swaminathan@Sun.COM 				} else {
98610997SSukumar.Swaminathan@Sun.COM 					rval = DDI_FAILURE;
98710997SSukumar.Swaminathan@Sun.COM 					goto out;
98810997SSukumar.Swaminathan@Sun.COM 				}
98910997SSukumar.Swaminathan@Sun.COM 			}
99010997SSukumar.Swaminathan@Sun.COM 		} else {
99110997SSukumar.Swaminathan@Sun.COM 			rval = DDI_FAILURE;
99210997SSukumar.Swaminathan@Sun.COM 			goto out;
99310997SSukumar.Swaminathan@Sun.COM 		}
99410997SSukumar.Swaminathan@Sun.COM 	} else {
99510997SSukumar.Swaminathan@Sun.COM 		rval = DDI_FAILURE;
99610997SSukumar.Swaminathan@Sun.COM 		goto out;
99710997SSukumar.Swaminathan@Sun.COM 	}
99810997SSukumar.Swaminathan@Sun.COM out:
99910997SSukumar.Swaminathan@Sun.COM 	ql_sem_unlock(qlge, QL_FLASH_SEM_MASK);
100010997SSukumar.Swaminathan@Sun.COM 
100110997SSukumar.Swaminathan@Sun.COM 	return (rval);
100210997SSukumar.Swaminathan@Sun.COM 
100310997SSukumar.Swaminathan@Sun.COM }
100410997SSukumar.Swaminathan@Sun.COM 
100510997SSukumar.Swaminathan@Sun.COM /*
100610997SSukumar.Swaminathan@Sun.COM  * ql_change_endian
100710997SSukumar.Swaminathan@Sun.COM  * Change endianess of byte array.
100810997SSukumar.Swaminathan@Sun.COM  */
100910997SSukumar.Swaminathan@Sun.COM void
ql_change_endian(uint8_t buf[],size_t size)101010997SSukumar.Swaminathan@Sun.COM ql_change_endian(uint8_t buf[], size_t size)
101110997SSukumar.Swaminathan@Sun.COM {
101210997SSukumar.Swaminathan@Sun.COM 	uint8_t byte;
101310997SSukumar.Swaminathan@Sun.COM 	size_t cnt1;
101410997SSukumar.Swaminathan@Sun.COM 	size_t cnt;
101510997SSukumar.Swaminathan@Sun.COM 
101610997SSukumar.Swaminathan@Sun.COM 	cnt1 = size - 1;
101710997SSukumar.Swaminathan@Sun.COM 	for (cnt = 0; cnt < size / 2; cnt++) {
101810997SSukumar.Swaminathan@Sun.COM 		byte = buf[cnt1];
101910997SSukumar.Swaminathan@Sun.COM 		buf[cnt1] = buf[cnt];
102010997SSukumar.Swaminathan@Sun.COM 		buf[cnt] = byte;
102110997SSukumar.Swaminathan@Sun.COM 		cnt1--;
102210997SSukumar.Swaminathan@Sun.COM 	}
102310997SSukumar.Swaminathan@Sun.COM }
102410997SSukumar.Swaminathan@Sun.COM 
102510997SSukumar.Swaminathan@Sun.COM static int
ql_wait_flash_reg_ready(qlge_t * qlge,uint32_t wait_bit)102610997SSukumar.Swaminathan@Sun.COM ql_wait_flash_reg_ready(qlge_t *qlge, uint32_t wait_bit)
102710997SSukumar.Swaminathan@Sun.COM {
102810997SSukumar.Swaminathan@Sun.COM 	uint32_t reg_status;
102910997SSukumar.Swaminathan@Sun.COM 	int rtn_val = DDI_SUCCESS;
103010997SSukumar.Swaminathan@Sun.COM 	uint32_t delay = 300000;
103110997SSukumar.Swaminathan@Sun.COM 
103210997SSukumar.Swaminathan@Sun.COM 	do {
103310997SSukumar.Swaminathan@Sun.COM 		reg_status = ql_read_reg(qlge, REG_FLASH_ADDRESS);
103410997SSukumar.Swaminathan@Sun.COM 		if (reg_status & FLASH_ERR_FLAG) {
103510997SSukumar.Swaminathan@Sun.COM 			cmn_err(CE_WARN,
103610997SSukumar.Swaminathan@Sun.COM 			    "%s(%d) flash address register error bit set!",
103710997SSukumar.Swaminathan@Sun.COM 			    __func__, qlge->instance);
103810997SSukumar.Swaminathan@Sun.COM 			rtn_val = DDI_FAILURE;
103910997SSukumar.Swaminathan@Sun.COM 			break;
104010997SSukumar.Swaminathan@Sun.COM 		}
104110997SSukumar.Swaminathan@Sun.COM 		if (reg_status & wait_bit) {
104210997SSukumar.Swaminathan@Sun.COM 			break;
104310997SSukumar.Swaminathan@Sun.COM 		}
104410997SSukumar.Swaminathan@Sun.COM 		drv_usecwait(10);
104510997SSukumar.Swaminathan@Sun.COM 	} while (--delay);
104610997SSukumar.Swaminathan@Sun.COM 
104710997SSukumar.Swaminathan@Sun.COM 	if (delay == 0) {
104810997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN,
104910997SSukumar.Swaminathan@Sun.COM 		    "%s(%d) timeout error!", __func__, qlge->instance);
1050*12073SSukumar.Swaminathan@Sun.COM 		if (qlge->fm_enable) {
1051*12073SSukumar.Swaminathan@Sun.COM 			ql_fm_ereport(qlge, DDI_FM_DEVICE_NO_RESPONSE);
1052*12073SSukumar.Swaminathan@Sun.COM 			atomic_or_32(&qlge->flags, ADAPTER_ERROR);
1053*12073SSukumar.Swaminathan@Sun.COM 			ddi_fm_service_impact(qlge->dip, DDI_SERVICE_LOST);
1054*12073SSukumar.Swaminathan@Sun.COM 		}
105510997SSukumar.Swaminathan@Sun.COM 		rtn_val = DDI_FAILURE;
105610997SSukumar.Swaminathan@Sun.COM 	}
105710997SSukumar.Swaminathan@Sun.COM 	return (rtn_val);
105810997SSukumar.Swaminathan@Sun.COM }
105910997SSukumar.Swaminathan@Sun.COM 
106010997SSukumar.Swaminathan@Sun.COM /*
106110997SSukumar.Swaminathan@Sun.COM  * ql_read_flash
106210997SSukumar.Swaminathan@Sun.COM  * Reads a 32bit word from FLASH.
106310997SSukumar.Swaminathan@Sun.COM  */
106410997SSukumar.Swaminathan@Sun.COM static int
ql_read_flash(qlge_t * qlge,uint32_t faddr,uint32_t * bp)106510997SSukumar.Swaminathan@Sun.COM ql_read_flash(qlge_t *qlge, uint32_t faddr, uint32_t *bp)
106610997SSukumar.Swaminathan@Sun.COM {
106710997SSukumar.Swaminathan@Sun.COM 	int rval = DDI_SUCCESS;
106810997SSukumar.Swaminathan@Sun.COM 
106910997SSukumar.Swaminathan@Sun.COM 	ql_write_reg(qlge, REG_FLASH_ADDRESS, faddr | FLASH_R_FLAG);
107010997SSukumar.Swaminathan@Sun.COM 
107110997SSukumar.Swaminathan@Sun.COM 	/* Wait for READ cycle to complete. */
107210997SSukumar.Swaminathan@Sun.COM 	rval = ql_wait_flash_reg_ready(qlge, FLASH_RDY_FLAG);
107310997SSukumar.Swaminathan@Sun.COM 
107410997SSukumar.Swaminathan@Sun.COM 	if (rval == DDI_SUCCESS) {
107510997SSukumar.Swaminathan@Sun.COM 		*bp = ql_read_reg(qlge, REG_FLASH_DATA);
107610997SSukumar.Swaminathan@Sun.COM 	}
107710997SSukumar.Swaminathan@Sun.COM 	return (rval);
107810997SSukumar.Swaminathan@Sun.COM }
107910997SSukumar.Swaminathan@Sun.COM 
108010997SSukumar.Swaminathan@Sun.COM static int
ql_read_flash_status(qlge_t * qlge,uint8_t * value)108110997SSukumar.Swaminathan@Sun.COM ql_read_flash_status(qlge_t *qlge, uint8_t *value)
108210997SSukumar.Swaminathan@Sun.COM {
108310997SSukumar.Swaminathan@Sun.COM 	int rtn_val = DDI_SUCCESS;
108410997SSukumar.Swaminathan@Sun.COM 	uint32_t data, cmd = FLASH_CONF_ADDR | FLASH_R_FLAG;
108510997SSukumar.Swaminathan@Sun.COM 
108610997SSukumar.Swaminathan@Sun.COM 	if ((rtn_val = ql_wait_flash_reg_ready(qlge, FLASH_RDY_FLAG))
108710997SSukumar.Swaminathan@Sun.COM 	    != DDI_SUCCESS) {
108810997SSukumar.Swaminathan@Sun.COM 		return (rtn_val);
108910997SSukumar.Swaminathan@Sun.COM 	}
109010997SSukumar.Swaminathan@Sun.COM 	cmd |= FLASH_RDSR_CMD /* 0x05 */;
109110997SSukumar.Swaminathan@Sun.COM 	ql_write_reg(qlge, REG_FLASH_ADDRESS, cmd);
109210997SSukumar.Swaminathan@Sun.COM 	if ((rtn_val = ql_wait_flash_reg_ready(qlge,
109310997SSukumar.Swaminathan@Sun.COM 	    FLASH_RDY_FLAG | FLASH_R_FLAG)) != DDI_SUCCESS) {
109410997SSukumar.Swaminathan@Sun.COM 		return (rtn_val);
109510997SSukumar.Swaminathan@Sun.COM 	}
109610997SSukumar.Swaminathan@Sun.COM 	data = ql_read_reg(qlge, REG_FLASH_DATA);
109710997SSukumar.Swaminathan@Sun.COM 	*value = (uint8_t)(data & 0xff);
109810997SSukumar.Swaminathan@Sun.COM 	return (rtn_val);
109910997SSukumar.Swaminathan@Sun.COM }
110010997SSukumar.Swaminathan@Sun.COM 
110110997SSukumar.Swaminathan@Sun.COM static int
ql_flash_write_enable(qlge_t * qlge)110210997SSukumar.Swaminathan@Sun.COM ql_flash_write_enable(qlge_t *qlge)
110310997SSukumar.Swaminathan@Sun.COM {
110410997SSukumar.Swaminathan@Sun.COM 	uint8_t reg_status;
110510997SSukumar.Swaminathan@Sun.COM 	int rtn_val = DDI_SUCCESS;
110610997SSukumar.Swaminathan@Sun.COM 	uint32_t cmd = FLASH_CONF_ADDR;
110710997SSukumar.Swaminathan@Sun.COM 	uint32_t delay = 300000;
110810997SSukumar.Swaminathan@Sun.COM 
110910997SSukumar.Swaminathan@Sun.COM 	if ((rtn_val = ql_wait_flash_reg_ready(qlge, FLASH_RDY_FLAG))
111010997SSukumar.Swaminathan@Sun.COM 	    != DDI_SUCCESS) {
111110997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN,
111210997SSukumar.Swaminathan@Sun.COM 		    "%s(%d) timeout!", __func__, qlge->instance);
111310997SSukumar.Swaminathan@Sun.COM 		rtn_val = DDI_FAILURE;
111410997SSukumar.Swaminathan@Sun.COM 		return (rtn_val);
111510997SSukumar.Swaminathan@Sun.COM 	}
111610997SSukumar.Swaminathan@Sun.COM 	cmd |= qlge->fdesc.write_enable_cmd;
111710997SSukumar.Swaminathan@Sun.COM 	ql_write_reg(qlge, REG_FLASH_ADDRESS, cmd);
111810997SSukumar.Swaminathan@Sun.COM 	/* wait for WEL bit set */
111910997SSukumar.Swaminathan@Sun.COM 	if ((rtn_val = ql_wait_flash_reg_ready(qlge, FLASH_RDY_FLAG))
112010997SSukumar.Swaminathan@Sun.COM 	    == DDI_SUCCESS) {
112110997SSukumar.Swaminathan@Sun.COM 		do {
112211016SSukumar.Swaminathan@Sun.COM 			(void) ql_read_flash_status(qlge, &reg_status);
112310997SSukumar.Swaminathan@Sun.COM 			if (reg_status & BIT_1)
112410997SSukumar.Swaminathan@Sun.COM 				break;
112510997SSukumar.Swaminathan@Sun.COM 			drv_usecwait(10);
112610997SSukumar.Swaminathan@Sun.COM 		} while (--delay);
112710997SSukumar.Swaminathan@Sun.COM 	}
112810997SSukumar.Swaminathan@Sun.COM 	if (delay == 0) {
112910997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN,
113010997SSukumar.Swaminathan@Sun.COM 		    "%s(%d) timeout error! flash status reg: %x",
113110997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance, reg_status);
113210997SSukumar.Swaminathan@Sun.COM 		rtn_val = DDI_FAILURE;
113310997SSukumar.Swaminathan@Sun.COM 	}
113410997SSukumar.Swaminathan@Sun.COM 	return (rtn_val);
113510997SSukumar.Swaminathan@Sun.COM }
113610997SSukumar.Swaminathan@Sun.COM 
113710997SSukumar.Swaminathan@Sun.COM static int
ql_flash_erase_sector(qlge_t * qlge,uint32_t sectorAddr)113810997SSukumar.Swaminathan@Sun.COM ql_flash_erase_sector(qlge_t *qlge, uint32_t sectorAddr)
113910997SSukumar.Swaminathan@Sun.COM {
114010997SSukumar.Swaminathan@Sun.COM 	int rtn_val = DDI_SUCCESS;
114110997SSukumar.Swaminathan@Sun.COM 	uint32_t data, cmd = FLASH_CONF_ADDR;
114210997SSukumar.Swaminathan@Sun.COM 	uint32_t delay = 300000;
114310997SSukumar.Swaminathan@Sun.COM 	uint8_t flash_status;
114410997SSukumar.Swaminathan@Sun.COM 
114510997SSukumar.Swaminathan@Sun.COM 	if ((rtn_val = ql_wait_flash_reg_ready(qlge, FLASH_RDY_FLAG))
114610997SSukumar.Swaminathan@Sun.COM 	    != DDI_SUCCESS) {
114710997SSukumar.Swaminathan@Sun.COM 		return (rtn_val);
114810997SSukumar.Swaminathan@Sun.COM 	}
114910997SSukumar.Swaminathan@Sun.COM 
115010997SSukumar.Swaminathan@Sun.COM 	cmd |= (0x0300 | qlge->fdesc.erase_cmd);
115110997SSukumar.Swaminathan@Sun.COM 	data = ((sectorAddr & 0xff) << 16) | (sectorAddr & 0xff00) |
115210997SSukumar.Swaminathan@Sun.COM 	    ((sectorAddr & 0xff0000) >> 16);
115310997SSukumar.Swaminathan@Sun.COM 
115410997SSukumar.Swaminathan@Sun.COM 	ql_write_reg(qlge, REG_FLASH_DATA, data);
115510997SSukumar.Swaminathan@Sun.COM 	ql_write_reg(qlge, REG_FLASH_ADDRESS, cmd);
115610997SSukumar.Swaminathan@Sun.COM 
115710997SSukumar.Swaminathan@Sun.COM 	if ((rtn_val = ql_wait_flash_reg_ready(qlge, FLASH_RDY_FLAG))
115810997SSukumar.Swaminathan@Sun.COM 	    == DDI_SUCCESS) {
115910997SSukumar.Swaminathan@Sun.COM 		/* wait Write In Progress (WIP) bit to reset */
116010997SSukumar.Swaminathan@Sun.COM 		do {
116111016SSukumar.Swaminathan@Sun.COM 			(void) ql_read_flash_status(qlge, &flash_status);
116210997SSukumar.Swaminathan@Sun.COM 			if ((flash_status & BIT_0 /* WIP */) == 0)
116310997SSukumar.Swaminathan@Sun.COM 				break;
116410997SSukumar.Swaminathan@Sun.COM 			drv_usecwait(10);
116510997SSukumar.Swaminathan@Sun.COM 		} while (--delay);
116610997SSukumar.Swaminathan@Sun.COM 	} else {
116710997SSukumar.Swaminathan@Sun.COM 		return (rtn_val);
116810997SSukumar.Swaminathan@Sun.COM 	}
116910997SSukumar.Swaminathan@Sun.COM 
117010997SSukumar.Swaminathan@Sun.COM 	if (delay == 0) {
117110997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN,
117210997SSukumar.Swaminathan@Sun.COM 		    "%s(%d) timeout error! flash status reg: %x",
117310997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance, flash_status);
117410997SSukumar.Swaminathan@Sun.COM 		rtn_val = DDI_FAILURE;
117510997SSukumar.Swaminathan@Sun.COM 	}
117610997SSukumar.Swaminathan@Sun.COM 	return (rtn_val);
117710997SSukumar.Swaminathan@Sun.COM }
117810997SSukumar.Swaminathan@Sun.COM 
117910997SSukumar.Swaminathan@Sun.COM /*
118010997SSukumar.Swaminathan@Sun.COM  * ql_write_flash
118110997SSukumar.Swaminathan@Sun.COM  * Writes a 32bit word to FLASH.
118210997SSukumar.Swaminathan@Sun.COM  */
118310997SSukumar.Swaminathan@Sun.COM static int
ql_write_flash(qlge_t * qlge,uint32_t addr,uint32_t data)118410997SSukumar.Swaminathan@Sun.COM ql_write_flash(qlge_t *qlge, uint32_t addr, uint32_t data)
118510997SSukumar.Swaminathan@Sun.COM {
118610997SSukumar.Swaminathan@Sun.COM 	int rval = DDI_SUCCESS;
118710997SSukumar.Swaminathan@Sun.COM 	uint32_t delay = 300000;
118810997SSukumar.Swaminathan@Sun.COM 	uint8_t flash_status;
118910997SSukumar.Swaminathan@Sun.COM 
119010997SSukumar.Swaminathan@Sun.COM 	ql_write_reg(qlge, REG_FLASH_DATA, data);
119111023SSukumar.Swaminathan@Sun.COM 	(void) ql_read_reg(qlge, REG_FLASH_DATA);
119210997SSukumar.Swaminathan@Sun.COM 	ql_write_reg(qlge, REG_FLASH_ADDRESS, addr);
119310997SSukumar.Swaminathan@Sun.COM 
119410997SSukumar.Swaminathan@Sun.COM 	if ((rval = ql_wait_flash_reg_ready(qlge, FLASH_RDY_FLAG))
119510997SSukumar.Swaminathan@Sun.COM 	    == DDI_SUCCESS) {
119610997SSukumar.Swaminathan@Sun.COM 		if ((addr & FLASH_ADDR_MASK) == FLASH_CONF_ADDR) {
119710997SSukumar.Swaminathan@Sun.COM 			/* wait Write In Progress (WIP) bit to reset */
119810997SSukumar.Swaminathan@Sun.COM 			do {
119911016SSukumar.Swaminathan@Sun.COM 				(void) ql_read_flash_status(qlge,
120011016SSukumar.Swaminathan@Sun.COM 				    &flash_status);
120110997SSukumar.Swaminathan@Sun.COM 				if ((flash_status & BIT_0 /* WIP */) == 0)
120210997SSukumar.Swaminathan@Sun.COM 					break;
120310997SSukumar.Swaminathan@Sun.COM 				drv_usecwait(10);
120410997SSukumar.Swaminathan@Sun.COM 			} while (--delay);
120510997SSukumar.Swaminathan@Sun.COM 		}
120610997SSukumar.Swaminathan@Sun.COM 	} else {
120710997SSukumar.Swaminathan@Sun.COM 		return (rval);
120810997SSukumar.Swaminathan@Sun.COM 	}
120910997SSukumar.Swaminathan@Sun.COM 
121010997SSukumar.Swaminathan@Sun.COM 	if (delay == 0) {
121110997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN,
121210997SSukumar.Swaminathan@Sun.COM 		    "%s(%d) timeout error! flash status reg: %x",
121310997SSukumar.Swaminathan@Sun.COM 		    __func__, qlge->instance, flash_status);
121410997SSukumar.Swaminathan@Sun.COM 		rval = DDI_FAILURE;
121510997SSukumar.Swaminathan@Sun.COM 	}
121610997SSukumar.Swaminathan@Sun.COM 
121710997SSukumar.Swaminathan@Sun.COM 	return (rval);
121810997SSukumar.Swaminathan@Sun.COM }
121910997SSukumar.Swaminathan@Sun.COM 
122010997SSukumar.Swaminathan@Sun.COM /*
122110997SSukumar.Swaminathan@Sun.COM  * ql_unprotect_flash
122210997SSukumar.Swaminathan@Sun.COM  * Enable writes
122310997SSukumar.Swaminathan@Sun.COM  */
122410997SSukumar.Swaminathan@Sun.COM static int
ql_unprotect_flash(qlge_t * qlge)122510997SSukumar.Swaminathan@Sun.COM ql_unprotect_flash(qlge_t *qlge)
122610997SSukumar.Swaminathan@Sun.COM {
122710997SSukumar.Swaminathan@Sun.COM 	int fdata, rtn_val;
122810997SSukumar.Swaminathan@Sun.COM 
122910997SSukumar.Swaminathan@Sun.COM 	if ((rtn_val = ql_flash_write_enable(qlge)) != DDI_SUCCESS) {
123010997SSukumar.Swaminathan@Sun.COM 		return (rtn_val);
123110997SSukumar.Swaminathan@Sun.COM 	}
123210997SSukumar.Swaminathan@Sun.COM 
123310997SSukumar.Swaminathan@Sun.COM 	if ((rtn_val = ql_wait_flash_reg_ready(qlge, FLASH_RDY_FLAG))
123410997SSukumar.Swaminathan@Sun.COM 	    != DDI_SUCCESS) {
123510997SSukumar.Swaminathan@Sun.COM 		return (rtn_val);
123610997SSukumar.Swaminathan@Sun.COM 	}
123710997SSukumar.Swaminathan@Sun.COM 
123810997SSukumar.Swaminathan@Sun.COM 	/*
123910997SSukumar.Swaminathan@Sun.COM 	 * Remove block write protection (SST and ST) and
124010997SSukumar.Swaminathan@Sun.COM 	 * Sector/Block Protection Register Lock (SST, ST, ATMEL).
124110997SSukumar.Swaminathan@Sun.COM 	 * Unprotect sectors.
124210997SSukumar.Swaminathan@Sun.COM 	 */
124310997SSukumar.Swaminathan@Sun.COM 	(void) ql_write_flash(qlge,
124410997SSukumar.Swaminathan@Sun.COM 	    FLASH_CONF_ADDR | 0x100 | qlge->fdesc.write_statusreg_cmd,
124510997SSukumar.Swaminathan@Sun.COM 	    qlge->fdesc.write_enable_bits);
124610997SSukumar.Swaminathan@Sun.COM 
124710997SSukumar.Swaminathan@Sun.COM 	if (qlge->fdesc.unprotect_sector_cmd != 0) {
124810997SSukumar.Swaminathan@Sun.COM 		for (fdata = 0; fdata < 0x10; fdata++) {
124910997SSukumar.Swaminathan@Sun.COM 			(void) ql_write_flash(qlge, FLASH_CONF_ADDR |
125010997SSukumar.Swaminathan@Sun.COM 			    0x300 | qlge->fdesc.unprotect_sector_cmd, fdata);
125110997SSukumar.Swaminathan@Sun.COM 		}
125210997SSukumar.Swaminathan@Sun.COM 
125310997SSukumar.Swaminathan@Sun.COM 		(void) ql_write_flash(qlge, FLASH_CONF_ADDR | 0x300 |
125410997SSukumar.Swaminathan@Sun.COM 		    qlge->fdesc.unprotect_sector_cmd, 0x00400f);
125510997SSukumar.Swaminathan@Sun.COM 		(void) ql_write_flash(qlge, FLASH_CONF_ADDR | 0x300 |
125610997SSukumar.Swaminathan@Sun.COM 		    qlge->fdesc.unprotect_sector_cmd, 0x00600f);
125710997SSukumar.Swaminathan@Sun.COM 		(void) ql_write_flash(qlge, FLASH_CONF_ADDR | 0x300 |
125810997SSukumar.Swaminathan@Sun.COM 		    qlge->fdesc.unprotect_sector_cmd, 0x00800f);
125910997SSukumar.Swaminathan@Sun.COM 	}
126010997SSukumar.Swaminathan@Sun.COM 	rtn_val = ql_wait_flash_reg_ready(qlge, FLASH_RDY_FLAG);
126110997SSukumar.Swaminathan@Sun.COM 	return (rtn_val);
126210997SSukumar.Swaminathan@Sun.COM }
126310997SSukumar.Swaminathan@Sun.COM 
126410997SSukumar.Swaminathan@Sun.COM /*
126510997SSukumar.Swaminathan@Sun.COM  * ql_protect_flash
126610997SSukumar.Swaminathan@Sun.COM  * Disable writes
126710997SSukumar.Swaminathan@Sun.COM  */
126810997SSukumar.Swaminathan@Sun.COM static int
ql_protect_flash(qlge_t * qlge)126910997SSukumar.Swaminathan@Sun.COM ql_protect_flash(qlge_t *qlge)
127010997SSukumar.Swaminathan@Sun.COM {
127110997SSukumar.Swaminathan@Sun.COM 	int fdata, rtn_val;
127210997SSukumar.Swaminathan@Sun.COM 
127310997SSukumar.Swaminathan@Sun.COM 	if ((rtn_val = ql_flash_write_enable(qlge)) != DDI_SUCCESS) {
127410997SSukumar.Swaminathan@Sun.COM 		return (rtn_val);
127510997SSukumar.Swaminathan@Sun.COM 	}
127610997SSukumar.Swaminathan@Sun.COM 
127710997SSukumar.Swaminathan@Sun.COM 	if ((rtn_val = ql_wait_flash_reg_ready(qlge, FLASH_RDY_FLAG))
127810997SSukumar.Swaminathan@Sun.COM 	    != DDI_SUCCESS) {
127910997SSukumar.Swaminathan@Sun.COM 		return (rtn_val);
128010997SSukumar.Swaminathan@Sun.COM 	}
128110997SSukumar.Swaminathan@Sun.COM 	/*
128210997SSukumar.Swaminathan@Sun.COM 	 * Protect sectors.
128310997SSukumar.Swaminathan@Sun.COM 	 * Set block write protection (SST and ST) and
128410997SSukumar.Swaminathan@Sun.COM 	 * Sector/Block Protection Register Lock (SST, ST, ATMEL).
128510997SSukumar.Swaminathan@Sun.COM 	 */
128610997SSukumar.Swaminathan@Sun.COM 
128710997SSukumar.Swaminathan@Sun.COM 	if (qlge->fdesc.protect_sector_cmd != 0) {
128810997SSukumar.Swaminathan@Sun.COM 		for (fdata = 0; fdata < 0x10; fdata++) {
128910997SSukumar.Swaminathan@Sun.COM 			(void) ql_write_flash(qlge, FLASH_CONF_ADDR |
129010997SSukumar.Swaminathan@Sun.COM 			    0x330 | qlge->fdesc.protect_sector_cmd, fdata);
129110997SSukumar.Swaminathan@Sun.COM 		}
129210997SSukumar.Swaminathan@Sun.COM 		(void) ql_write_flash(qlge, FLASH_CONF_ADDR | 0x330 |
129310997SSukumar.Swaminathan@Sun.COM 		    qlge->fdesc.protect_sector_cmd, 0x00400f);
129410997SSukumar.Swaminathan@Sun.COM 		(void) ql_write_flash(qlge, FLASH_CONF_ADDR | 0x330 |
129510997SSukumar.Swaminathan@Sun.COM 		    qlge->fdesc.protect_sector_cmd, 0x00600f);
129610997SSukumar.Swaminathan@Sun.COM 		(void) ql_write_flash(qlge, FLASH_CONF_ADDR | 0x330 |
129710997SSukumar.Swaminathan@Sun.COM 		    qlge->fdesc.protect_sector_cmd, 0x00800f);
129810997SSukumar.Swaminathan@Sun.COM 
129910997SSukumar.Swaminathan@Sun.COM 		(void) ql_write_flash(qlge,
130010997SSukumar.Swaminathan@Sun.COM 		    FLASH_CONF_ADDR | 0x101, 0x80);
130110997SSukumar.Swaminathan@Sun.COM 	} else {
130210997SSukumar.Swaminathan@Sun.COM 		(void) ql_write_flash(qlge,
130310997SSukumar.Swaminathan@Sun.COM 		    FLASH_CONF_ADDR | 0x100 | qlge->fdesc.write_statusreg_cmd,
130410997SSukumar.Swaminathan@Sun.COM 		    qlge->fdesc.write_disable_bits /* 0x9c */);
130510997SSukumar.Swaminathan@Sun.COM 	}
130610997SSukumar.Swaminathan@Sun.COM 
130710997SSukumar.Swaminathan@Sun.COM 	rtn_val = ql_wait_flash_reg_ready(qlge, FLASH_RDY_FLAG);
130810997SSukumar.Swaminathan@Sun.COM 	return (rtn_val);
130910997SSukumar.Swaminathan@Sun.COM }
131010997SSukumar.Swaminathan@Sun.COM 
131110997SSukumar.Swaminathan@Sun.COM /*
131210997SSukumar.Swaminathan@Sun.COM  * ql_write_flash_test
131310997SSukumar.Swaminathan@Sun.COM  * test write to a flash sector that is not being used
131410997SSukumar.Swaminathan@Sun.COM  */
131510997SSukumar.Swaminathan@Sun.COM void
ql_write_flash_test(qlge_t * qlge,uint32_t test_addr)131610997SSukumar.Swaminathan@Sun.COM ql_write_flash_test(qlge_t *qlge, uint32_t test_addr)
131710997SSukumar.Swaminathan@Sun.COM {
131810997SSukumar.Swaminathan@Sun.COM 	uint32_t old_data, data;
131910997SSukumar.Swaminathan@Sun.COM 	uint32_t addr = 0;
132010997SSukumar.Swaminathan@Sun.COM 
132110997SSukumar.Swaminathan@Sun.COM 	addr = (test_addr / 4);
132211016SSukumar.Swaminathan@Sun.COM 	(void) ql_read_flash(qlge, addr, &old_data);
132310997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("read addr %x old value %x\n", test_addr,
132410997SSukumar.Swaminathan@Sun.COM 	    old_data));
132510997SSukumar.Swaminathan@Sun.COM 
132610997SSukumar.Swaminathan@Sun.COM 	/* enable writing to flash */
132711016SSukumar.Swaminathan@Sun.COM 	(void) ql_unprotect_flash(qlge);
132810997SSukumar.Swaminathan@Sun.COM 
132910997SSukumar.Swaminathan@Sun.COM 	/* erase the sector */
133011016SSukumar.Swaminathan@Sun.COM 	(void) ql_flash_erase_sector(qlge, test_addr);
133111016SSukumar.Swaminathan@Sun.COM 	(void) ql_read_flash(qlge, addr, &data);
133210997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("after sector erase, addr %x value %x\n",
133310997SSukumar.Swaminathan@Sun.COM 	    test_addr, data));
133410997SSukumar.Swaminathan@Sun.COM 
133510997SSukumar.Swaminathan@Sun.COM 	/* write new value to it and read back to confirm */
133610997SSukumar.Swaminathan@Sun.COM 	data = 0x33445566;
133711016SSukumar.Swaminathan@Sun.COM 	(void) ql_write_flash(qlge, addr, data);
133810997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("new value written to addr %x value %x\n",
133910997SSukumar.Swaminathan@Sun.COM 	    test_addr, data));
134011016SSukumar.Swaminathan@Sun.COM 	(void) ql_read_flash(qlge, addr, &data);
134110997SSukumar.Swaminathan@Sun.COM 	if (data != 0x33445566) {
134210997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN, "flash write test failed, get data %x"
134310997SSukumar.Swaminathan@Sun.COM 		    " after writing", data);
134410997SSukumar.Swaminathan@Sun.COM 	}
134510997SSukumar.Swaminathan@Sun.COM 
134610997SSukumar.Swaminathan@Sun.COM 	/* write old value to it and read back to restore */
134711016SSukumar.Swaminathan@Sun.COM 	(void) ql_flash_erase_sector(qlge, test_addr);
134811016SSukumar.Swaminathan@Sun.COM 	(void) ql_write_flash(qlge, addr, old_data);
134911016SSukumar.Swaminathan@Sun.COM 	(void) ql_read_flash(qlge, addr, &data);
135010997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("write back old value addr %x value %x\n",
135110997SSukumar.Swaminathan@Sun.COM 	    test_addr, data));
135210997SSukumar.Swaminathan@Sun.COM 
135310997SSukumar.Swaminathan@Sun.COM 	/* test done, protect the flash to forbid any more flash writting */
135411016SSukumar.Swaminathan@Sun.COM 	(void) ql_protect_flash(qlge);
135510997SSukumar.Swaminathan@Sun.COM 
135610997SSukumar.Swaminathan@Sun.COM }
135710997SSukumar.Swaminathan@Sun.COM 
135810997SSukumar.Swaminathan@Sun.COM 
135910997SSukumar.Swaminathan@Sun.COM void
ql_write_flash_test2(qlge_t * qlge,uint32_t test_addr)136010997SSukumar.Swaminathan@Sun.COM ql_write_flash_test2(qlge_t *qlge, uint32_t test_addr)
136110997SSukumar.Swaminathan@Sun.COM {
136210997SSukumar.Swaminathan@Sun.COM 	uint32_t data, old_data;
136310997SSukumar.Swaminathan@Sun.COM 
136411016SSukumar.Swaminathan@Sun.COM 	(void) qlge_dump_fcode(qlge, (uint8_t *)&old_data, sizeof (old_data),
136510997SSukumar.Swaminathan@Sun.COM 	    test_addr);
136610997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("read addr %x old value %x\n",
136710997SSukumar.Swaminathan@Sun.COM 	    test_addr, old_data));
136810997SSukumar.Swaminathan@Sun.COM 
136910997SSukumar.Swaminathan@Sun.COM 	data = 0x12345678;
137010997SSukumar.Swaminathan@Sun.COM 
137110997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("write new test value %x\n", data));
137211023SSukumar.Swaminathan@Sun.COM 	(void) qlge_load_flash(qlge, (uint8_t *)&data, sizeof (data),
137311023SSukumar.Swaminathan@Sun.COM 	    test_addr);
137411016SSukumar.Swaminathan@Sun.COM 	(void) qlge_dump_fcode(qlge, (uint8_t *)&data, sizeof (data),
137511016SSukumar.Swaminathan@Sun.COM 	    test_addr);
137610997SSukumar.Swaminathan@Sun.COM 	if (data != 0x12345678) {
137710997SSukumar.Swaminathan@Sun.COM 		cmn_err(CE_WARN,
137810997SSukumar.Swaminathan@Sun.COM 		    "flash write test failed, get data %x after writing",
137910997SSukumar.Swaminathan@Sun.COM 		    data);
138010997SSukumar.Swaminathan@Sun.COM 	}
138110997SSukumar.Swaminathan@Sun.COM 	/* write old value to it and read back to restore */
138211023SSukumar.Swaminathan@Sun.COM 	(void) qlge_load_flash(qlge, (uint8_t *)&old_data, sizeof (old_data),
138310997SSukumar.Swaminathan@Sun.COM 	    test_addr);
138411016SSukumar.Swaminathan@Sun.COM 	(void) qlge_dump_fcode(qlge, (uint8_t *)&data, sizeof (data),
138510997SSukumar.Swaminathan@Sun.COM 	    test_addr);
138610997SSukumar.Swaminathan@Sun.COM 	QL_PRINT(DBG_FLASH, ("write back old value addr %x value %x verified\n",
138710997SSukumar.Swaminathan@Sun.COM 	    test_addr, data));
138810997SSukumar.Swaminathan@Sun.COM }
138910997SSukumar.Swaminathan@Sun.COM 
139010997SSukumar.Swaminathan@Sun.COM /*
139110997SSukumar.Swaminathan@Sun.COM  * ql_sem_flash_lock
139210997SSukumar.Swaminathan@Sun.COM  * Flash memory is a shared resource amoung various PCI Functions, so,
139310997SSukumar.Swaminathan@Sun.COM  * anyone wants to access flash memory, it needs to lock it first.
139410997SSukumar.Swaminathan@Sun.COM  */
139510997SSukumar.Swaminathan@Sun.COM int
ql_sem_flash_lock(qlge_t * qlge)139610997SSukumar.Swaminathan@Sun.COM ql_sem_flash_lock(qlge_t *qlge)
139710997SSukumar.Swaminathan@Sun.COM {
139810997SSukumar.Swaminathan@Sun.COM 	int rval = DDI_SUCCESS;
139910997SSukumar.Swaminathan@Sun.COM 
140010997SSukumar.Swaminathan@Sun.COM 	/* Get semaphore to access Flash Address and Flash Data Registers */
140110997SSukumar.Swaminathan@Sun.COM 	if (ql_sem_spinlock(qlge, QL_FLASH_SEM_MASK)) {
140210997SSukumar.Swaminathan@Sun.COM 		rval = DDI_FAILURE;
140310997SSukumar.Swaminathan@Sun.COM 	}
140410997SSukumar.Swaminathan@Sun.COM 	return (rval);
140510997SSukumar.Swaminathan@Sun.COM }
140610997SSukumar.Swaminathan@Sun.COM 
140710997SSukumar.Swaminathan@Sun.COM void
ql_sem_flash_unlock(qlge_t * qlge)140810997SSukumar.Swaminathan@Sun.COM ql_sem_flash_unlock(qlge_t *qlge)
140910997SSukumar.Swaminathan@Sun.COM {
141010997SSukumar.Swaminathan@Sun.COM 	ql_sem_unlock(qlge, QL_FLASH_SEM_MASK);
141110997SSukumar.Swaminathan@Sun.COM }
1412