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, ®_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