1. Updated Copyright Information
2. Added Flash Read/Update Support 3. Fixed TSO Handling Submitted by: David C Somayajulu (davidcs@freebsd.org) Reviewed by: George Neville-Neil (gnn@freebsd.org) Approved by: George Neville-Neil (gnn@freebsd.org)
This commit is contained in:
parent
16e073e57a
commit
088fc97186
@ -93,7 +93,7 @@ Technical Support at any phase of integration for assistance. QLogic
|
||||
Technical Support can be reached by the following methods:
|
||||
Web: http://support.qlogic.com
|
||||
E-mail: support@qlogic.com
|
||||
(c) Copyright 2011. All rights reserved worldwide. QLogic, the QLogic
|
||||
(c) Copyright 2013. All rights reserved worldwide. QLogic, the QLogic
|
||||
logo, and the Powered by QLogic logo are registered trademarks of
|
||||
QLogic Corporation. All other brand and product names are trademarks
|
||||
or registered trademarks of their respective owners.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -194,6 +194,8 @@ struct qla_host {
|
||||
/* debug stuff */
|
||||
volatile const char *qla_lock;
|
||||
volatile const char *qla_unlock;
|
||||
|
||||
uint8_t fw_ver_str[32];
|
||||
};
|
||||
typedef struct qla_host qla_host_t;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -56,14 +56,6 @@ extern void qla_start(struct ifnet *ifp);
|
||||
extern int qla_get_mbuf(qla_host_t *ha, qla_rx_buf_t *rxb, struct mbuf *nmp,
|
||||
uint32_t jumbo);
|
||||
|
||||
|
||||
/*
|
||||
* from qla_flash.c
|
||||
*/
|
||||
extern int qla_flash_rd32_words(qla_host_t *ha, uint32_t addr,
|
||||
uint32_t *val, uint32_t num);
|
||||
extern int qla_flash_rd32(qla_host_t *ha, uint32_t addr, uint32_t *val);
|
||||
|
||||
/*
|
||||
* from qla_hw.c
|
||||
*/
|
||||
@ -97,6 +89,14 @@ extern int qla_init_hw(qla_host_t *ha);
|
||||
extern int qla_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val,
|
||||
uint32_t rd);
|
||||
extern int qla_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data);
|
||||
extern int qla_flash_rd32_words(qla_host_t *ha, uint32_t addr,
|
||||
uint32_t *val, uint32_t num);
|
||||
extern int qla_flash_rd32(qla_host_t *ha, uint32_t addr, uint32_t *val);
|
||||
extern int qla_fw_update(qla_host_t *ha, void *fdata, uint32_t off,
|
||||
uint32_t size);
|
||||
extern int qla_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size);
|
||||
extern int qla_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size,
|
||||
void *buf, uint32_t pattern);
|
||||
|
||||
/*
|
||||
* from qla_ioctl.c
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2012 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -711,20 +711,18 @@ qla_config_ipv4_addr(qla_host_t *ha, uint32_t ipv4_addr)
|
||||
* Ring Structure are plugged in.
|
||||
*/
|
||||
static int
|
||||
qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd)
|
||||
qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd, uint8_t *hdr)
|
||||
{
|
||||
struct ether_vlan_header *eh;
|
||||
struct ip *ip = NULL;
|
||||
struct tcphdr *th = NULL;
|
||||
uint32_t ehdrlen, hdrlen, ip_hlen, tcp_hlen;
|
||||
uint32_t ehdrlen, hdrlen = 0, ip_hlen, tcp_hlen, tcp_opt_off;
|
||||
uint16_t etype, opcode, offload = 1;
|
||||
uint8_t *tcp_opt;
|
||||
device_t dev;
|
||||
|
||||
dev = ha->pci_dev;
|
||||
|
||||
if (mp->m_pkthdr.len <= ha->max_frame_size)
|
||||
return (-1);
|
||||
|
||||
eh = mtod(mp, struct ether_vlan_header *);
|
||||
|
||||
if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN)) {
|
||||
@ -737,14 +735,26 @@ qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd)
|
||||
|
||||
switch (etype) {
|
||||
case ETHERTYPE_IP:
|
||||
|
||||
tcp_opt_off = ehdrlen + sizeof(struct ip) +
|
||||
sizeof(struct tcphdr);
|
||||
|
||||
if (mp->m_len < tcp_opt_off) {
|
||||
m_copydata(mp, 0, tcp_opt_off, hdr);
|
||||
ip = (struct ip *)hdr;
|
||||
} else {
|
||||
ip = (struct ip *)(mp->m_data + ehdrlen);
|
||||
}
|
||||
|
||||
ip_hlen = ip->ip_hl << 2;
|
||||
opcode = Q8_TX_CMD_OP_XMT_TCP_LSO;
|
||||
|
||||
if (ip->ip_p != IPPROTO_TCP) {
|
||||
if ((ip->ip_p != IPPROTO_TCP) ||
|
||||
(ip_hlen != sizeof (struct ip))) {
|
||||
offload = 0;
|
||||
} else
|
||||
} else {
|
||||
th = (struct tcphdr *)((caddr_t)ip + ip_hlen);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -758,11 +768,43 @@ qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd)
|
||||
|
||||
tcp_hlen = th->th_off << 2;
|
||||
|
||||
|
||||
hdrlen = ehdrlen + ip_hlen + tcp_hlen;
|
||||
|
||||
if (mp->m_len < hdrlen) {
|
||||
device_printf(dev, "%s: (mp->m_len < hdrlen)\n", __func__);
|
||||
return (-1);
|
||||
if (mp->m_len < tcp_opt_off) {
|
||||
if (tcp_hlen > sizeof(struct tcphdr)) {
|
||||
m_copydata(mp, tcp_opt_off,
|
||||
(tcp_hlen - sizeof(struct tcphdr)),
|
||||
&hdr[tcp_opt_off]);
|
||||
}
|
||||
} else {
|
||||
m_copydata(mp, 0, hdrlen, hdr);
|
||||
}
|
||||
}
|
||||
|
||||
if ((mp->m_pkthdr.csum_flags & CSUM_TSO) == 0) {
|
||||
|
||||
/* If TCP options are preset only time stamp option is supported */
|
||||
if ((tcp_hlen - sizeof(struct tcphdr)) != 10)
|
||||
return -1;
|
||||
else {
|
||||
|
||||
if (mp->m_len < hdrlen) {
|
||||
tcp_opt = &hdr[tcp_opt_off];
|
||||
} else {
|
||||
tcp_opt = (uint8_t *)(mp->m_data + tcp_opt_off);
|
||||
}
|
||||
|
||||
if ((*tcp_opt != 0x01) || (*(tcp_opt + 1) != 0x01) ||
|
||||
(*(tcp_opt + 2) != 0x08) || (*(tcp_opt + 2) != 10)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
tx_cmd->mss = ha->max_frame_size - ETHER_CRC_LEN - hdrlen;
|
||||
} else {
|
||||
tx_cmd->mss = mp->m_pkthdr.tso_segsz;
|
||||
}
|
||||
|
||||
tx_cmd->flags_opcode = opcode ;
|
||||
@ -776,6 +818,10 @@ qla_tx_tso(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd)
|
||||
tx_cmd->flags_opcode = Q8_TX_CMD_FLAGS_MULTICAST;
|
||||
}
|
||||
|
||||
if (mp->m_len < hdrlen) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -815,7 +861,7 @@ qla_tx_chksum(qla_host_t *ha, struct mbuf *mp, q80_tx_cmd_t *tx_cmd)
|
||||
case ETHERTYPE_IP:
|
||||
ip = (struct ip *)(mp->m_data + ehdrlen);
|
||||
|
||||
ip_hlen = ip->ip_hl << 2;
|
||||
ip_hlen = sizeof (struct ip);
|
||||
|
||||
if (mp->m_len < (ehdrlen + ip_hlen)) {
|
||||
device_printf(dev, "%s: ipv4 mlen\n", __func__);
|
||||
@ -886,7 +932,8 @@ qla_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
|
||||
uint32_t num_tx_cmds, hdr_len = 0;
|
||||
uint32_t total_length = 0, bytes, tx_cmd_count = 0;
|
||||
device_t dev;
|
||||
int i;
|
||||
int i, ret;
|
||||
uint8_t *src = NULL, *dst = NULL;
|
||||
|
||||
dev = ha->pci_dev;
|
||||
|
||||
@ -902,10 +949,16 @@ qla_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
|
||||
__func__, total_length);
|
||||
return (-1);
|
||||
}
|
||||
eh = mtod(mp, struct ether_vlan_header *);
|
||||
|
||||
if ((mp->m_pkthdr.len > ha->max_frame_size)||(nsegs > Q8_TX_MAX_SEGMENTS)) {
|
||||
|
||||
bzero((void *)&tso_cmd, sizeof(q80_tx_cmd_t));
|
||||
|
||||
if (qla_tx_tso(ha, mp, &tso_cmd) == 0) {
|
||||
src = ha->hw.frame_hdr;
|
||||
ret = qla_tx_tso(ha, mp, &tso_cmd, src);
|
||||
|
||||
if (!(ret & ~1)) {
|
||||
/* find the additional tx_cmd descriptors required */
|
||||
|
||||
hdr_len = tso_cmd.total_hdr_len;
|
||||
@ -922,6 +975,10 @@ qla_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
|
||||
num_tx_cmds++;
|
||||
}
|
||||
hdr_len = tso_cmd.total_hdr_len;
|
||||
|
||||
if (ret == 0)
|
||||
src = (uint8_t *)eh;
|
||||
}
|
||||
}
|
||||
|
||||
if (hw->txr_free <= (num_tx_cmds + QLA_TX_MIN_FREE)) {
|
||||
@ -957,7 +1014,6 @@ qla_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
|
||||
bcopy(&tso_cmd, tx_cmd, sizeof(q80_tx_cmd_t));
|
||||
}
|
||||
|
||||
eh = mtod(mp, struct ether_vlan_header *);
|
||||
if (eh->evl_encap_proto == htons(ETHERTYPE_VLAN))
|
||||
tx_cmd->flags_opcode |= Q8_TX_CMD_FLAGS_VLAN_TAGGED;
|
||||
else if (mp->m_flags & M_VLANTAG) {
|
||||
@ -1015,9 +1071,6 @@ qla_hw_send(qla_host_t *ha, bus_dma_segment_t *segs, int nsegs,
|
||||
|
||||
if (hdr_len) {
|
||||
/* TSO : Copy the header in the following tx cmd descriptors */
|
||||
uint8_t *src, *dst;
|
||||
|
||||
src = (uint8_t *)eh;
|
||||
|
||||
tx_cmd = &hw->tx_ring_base[hw->txr_next];
|
||||
bzero((void *)tx_cmd, sizeof(q80_tx_cmd_t));
|
||||
@ -1704,6 +1757,7 @@ void
|
||||
qla_update_link_state(qla_host_t *ha)
|
||||
{
|
||||
uint32_t link_state;
|
||||
uint32_t prev_link_state;
|
||||
|
||||
if (!(ha->ifp->if_drv_flags & IFF_DRV_RUNNING)) {
|
||||
ha->hw.flags.link_up = 0;
|
||||
@ -1711,10 +1765,20 @@ qla_update_link_state(qla_host_t *ha)
|
||||
}
|
||||
link_state = READ_REG32(ha, Q8_LINK_STATE);
|
||||
|
||||
prev_link_state = ha->hw.flags.link_up;
|
||||
|
||||
if (ha->pci_func == 0)
|
||||
ha->hw.flags.link_up = (((link_state & 0xF) == 1)? 1 : 0);
|
||||
else
|
||||
ha->hw.flags.link_up = ((((link_state >> 4)& 0xF) == 1)? 1 : 0);
|
||||
|
||||
if (prev_link_state != ha->hw.flags.link_up) {
|
||||
if (ha->hw.flags.link_up) {
|
||||
if_link_state_change(ha->ifp, LINK_STATE_UP);
|
||||
} else {
|
||||
if_link_state_change(ha->ifp, LINK_STATE_DOWN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -724,6 +724,8 @@ typedef struct _qla_sds {
|
||||
volatile uint32_t rcv_active;
|
||||
} qla_sds_t;
|
||||
|
||||
#define QL_FRAME_HDR_SIZE (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN +\
|
||||
sizeof (struct ip) + sizeof (struct tcphdr) + 16)
|
||||
/*
|
||||
* struct for storing hardware specific information for a given interface
|
||||
*/
|
||||
@ -791,6 +793,8 @@ typedef struct _qla_hw {
|
||||
bus_addr_t rx_cntxt_rsp_paddr;
|
||||
|
||||
qla_sds_t sds[MAX_SDS_RINGS];
|
||||
|
||||
uint8_t frame_hdr[QL_FRAME_HDR_SIZE];
|
||||
} qla_hw_t;
|
||||
|
||||
#define QL_UPDATE_RDS_PRODUCER_INDEX(ha, i, val) \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -82,10 +82,15 @@ qla_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
|
||||
int rval = 0;
|
||||
qla_reg_val_t *rv;
|
||||
qla_rd_flash_t *rdf;
|
||||
qla_wr_flash_t *wrf;
|
||||
qla_rd_pci_ids_t *pci_ids;
|
||||
device_t pci_dev;
|
||||
|
||||
if ((ha = (qla_host_t *)dev->si_drv1) == NULL)
|
||||
return ENXIO;
|
||||
|
||||
pci_dev= ha->pci_dev;
|
||||
|
||||
switch(cmd) {
|
||||
|
||||
case QLA_RDWR_REG:
|
||||
@ -110,6 +115,30 @@ qla_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
|
||||
if ((rval = qla_rd_flash32(ha, rdf->off, &rdf->data)))
|
||||
rval = ENXIO;
|
||||
break;
|
||||
|
||||
case QLA_WR_FLASH:
|
||||
wrf = (qla_wr_flash_t *)data;
|
||||
if ((rval = qla_wr_flash_buffer(ha, wrf->off, wrf->size,
|
||||
wrf->buffer, wrf->pattern)))
|
||||
rval = ENXIO;
|
||||
break;
|
||||
|
||||
|
||||
case QLA_ERASE_FLASH:
|
||||
if (qla_erase_flash(ha, ((qla_erase_flash_t *)data)->off,
|
||||
((qla_erase_flash_t *)data)->size))
|
||||
rval = ENXIO;
|
||||
break;
|
||||
|
||||
case QLA_RD_PCI_IDS:
|
||||
pci_ids = (qla_rd_pci_ids_t *)data;
|
||||
pci_ids->ven_id = pci_get_vendor(pci_dev);
|
||||
pci_ids->dev_id = pci_get_device(pci_dev);
|
||||
pci_ids->subsys_ven_id = pci_get_subvendor(pci_dev);
|
||||
pci_ids->subsys_dev_id = pci_get_subdevice(pci_dev);
|
||||
pci_ids->rev_id = pci_read_config(pci_dev, PCIR_REVID, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -50,6 +50,28 @@ struct qla_rd_flash {
|
||||
};
|
||||
typedef struct qla_rd_flash qla_rd_flash_t;
|
||||
|
||||
struct qla_wr_flash {
|
||||
uint32_t off;
|
||||
uint32_t size;
|
||||
void *buffer;
|
||||
uint32_t pattern;
|
||||
};
|
||||
typedef struct qla_wr_flash qla_wr_flash_t;
|
||||
|
||||
struct qla_erase_flash {
|
||||
uint32_t off;
|
||||
uint32_t size;
|
||||
};
|
||||
typedef struct qla_erase_flash qla_erase_flash_t;
|
||||
|
||||
struct qla_rd_pci_ids {
|
||||
uint16_t ven_id;
|
||||
uint16_t dev_id;
|
||||
uint16_t subsys_ven_id;
|
||||
uint16_t subsys_dev_id;
|
||||
uint8_t rev_id;
|
||||
};
|
||||
typedef struct qla_rd_pci_ids qla_rd_pci_ids_t;
|
||||
|
||||
/*
|
||||
* Read/Write Register
|
||||
@ -61,4 +83,19 @@ typedef struct qla_rd_flash qla_rd_flash_t;
|
||||
*/
|
||||
#define QLA_RD_FLASH _IOWR('q', 2, qla_rd_flash_t)
|
||||
|
||||
/*
|
||||
* Write Flash
|
||||
*/
|
||||
#define QLA_WR_FLASH _IOWR('q', 3, qla_wr_flash_t)
|
||||
|
||||
/*
|
||||
* Erase Flash
|
||||
*/
|
||||
#define QLA_ERASE_FLASH _IOWR('q', 5, qla_erase_flash_t)
|
||||
|
||||
/*
|
||||
* Read PCI IDs
|
||||
*/
|
||||
#define QLA_RD_PCI_IDS _IOWR('q', 6, qla_rd_pci_ids_t)
|
||||
|
||||
#endif /* #ifndef _QLA_IOCTL_H_ */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -344,6 +344,17 @@ qla_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
qla_p3p_sem_lock2(qla_host_t *ha)
|
||||
{
|
||||
if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) {
|
||||
device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__);
|
||||
return (-1);
|
||||
}
|
||||
WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Name: qla_int_to_pci_addr_map
|
||||
* Function: Convert's Internal(CRB) Address to Indirect Address
|
||||
@ -402,7 +413,7 @@ qla_filter_pci_addr(qla_host_t *ha, uint32_t addr)
|
||||
static int
|
||||
qla_crb_init(qla_host_t *ha)
|
||||
{
|
||||
uint32_t val, sig;
|
||||
uint32_t val = 0, sig = 0;
|
||||
uint32_t offset, count, i;
|
||||
addr_val_t *addr_val_map, *avmap;
|
||||
|
||||
@ -611,6 +622,21 @@ qla_init_hw(qla_host_t *ha)
|
||||
if (val != CMDPEG_PHAN_INIT_COMPLETE) {
|
||||
ret = qla_init_from_flash(ha);
|
||||
qla_mdelay(__func__, 100);
|
||||
} else {
|
||||
ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
|
||||
ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
|
||||
ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
|
||||
|
||||
if (qla_rd_flash32(ha, 0x100004, &val) == 0) {
|
||||
|
||||
if (((val & 0xFF) != ha->fw_ver_major) ||
|
||||
(((val >> 8) & 0xFF) != ha->fw_ver_minor) ||
|
||||
(((val >> 16) & 0xFF) != ha->fw_ver_sub)) {
|
||||
|
||||
ret = qla_init_from_flash(ha);
|
||||
qla_mdelay(__func__, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qla_init_exit:
|
||||
@ -622,3 +648,403 @@ qla_init_hw(qla_host_t *ha)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
qla_wait_for_flash_busy(qla_host_t *ha)
|
||||
{
|
||||
uint32_t count = 100;
|
||||
uint32_t val;
|
||||
|
||||
QLA_USEC_DELAY(100);
|
||||
|
||||
while (count--) {
|
||||
val = READ_OFFSET32(ha, Q8_ROM_STATUS);
|
||||
|
||||
if (val & BIT_1)
|
||||
return 0;
|
||||
qla_mdelay(__func__, 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
qla_flash_write_enable(qla_host_t *ha)
|
||||
{
|
||||
uint32_t val, rval;
|
||||
|
||||
val = 0;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
|
||||
|
||||
val = ROM_OPCODE_WR_ENABLE;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
|
||||
|
||||
rval = qla_wait_for_flash_busy(ha);
|
||||
|
||||
if (rval)
|
||||
device_printf(ha->pci_dev, "%s: failed \n", __func__);
|
||||
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static int
|
||||
qla_flash_unprotect(qla_host_t *ha)
|
||||
{
|
||||
uint32_t val, rval;
|
||||
|
||||
if (qla_flash_write_enable(ha) != 0)
|
||||
return(-1);
|
||||
|
||||
val = 0;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
|
||||
|
||||
val = ROM_OPCODE_WR_STATUS_REG;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
|
||||
|
||||
rval = qla_wait_for_flash_busy(ha);
|
||||
|
||||
if (rval) {
|
||||
device_printf(ha->pci_dev, "%s: failed \n", __func__);
|
||||
return rval;
|
||||
}
|
||||
|
||||
if (qla_flash_write_enable(ha) != 0)
|
||||
return(-1);
|
||||
|
||||
val = 0;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
|
||||
|
||||
val = ROM_OPCODE_WR_STATUS_REG;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
|
||||
|
||||
rval = qla_wait_for_flash_busy(ha);
|
||||
|
||||
if (rval)
|
||||
device_printf(ha->pci_dev, "%s: failed \n", __func__);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int
|
||||
qla_flash_protect(qla_host_t *ha)
|
||||
{
|
||||
uint32_t val, rval;
|
||||
|
||||
if (qla_flash_write_enable(ha) != 0)
|
||||
return(-1);
|
||||
|
||||
val = 0x9C;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
|
||||
|
||||
val = ROM_OPCODE_WR_STATUS_REG;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
|
||||
|
||||
rval = qla_wait_for_flash_busy(ha);
|
||||
|
||||
if (rval)
|
||||
device_printf(ha->pci_dev, "%s: failed \n", __func__);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
qla_flash_get_status(qla_host_t *ha)
|
||||
{
|
||||
uint32_t count = 1000;
|
||||
uint32_t val, rval;
|
||||
|
||||
while (count--) {
|
||||
val = 0;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
|
||||
|
||||
val = ROM_OPCODE_RD_STATUS_REG;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
|
||||
|
||||
rval = qla_wait_for_flash_busy(ha);
|
||||
|
||||
if (rval == 0) {
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
|
||||
|
||||
if ((val & BIT_0) == 0)
|
||||
return (val);
|
||||
}
|
||||
qla_mdelay(__func__, 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
qla_wait_for_flash_unprotect(qla_host_t *ha)
|
||||
{
|
||||
uint32_t delay = 1000;
|
||||
|
||||
while (delay--) {
|
||||
|
||||
if (qla_flash_get_status(ha) == 0)
|
||||
return 0;
|
||||
|
||||
qla_mdelay(__func__, 1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
qla_wait_for_flash_protect(qla_host_t *ha)
|
||||
{
|
||||
uint32_t delay = 1000;
|
||||
|
||||
while (delay--) {
|
||||
|
||||
if (qla_flash_get_status(ha) == 0x9C)
|
||||
return 0;
|
||||
|
||||
qla_mdelay(__func__, 1);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
qla_erase_flash_sector(qla_host_t *ha, uint32_t start)
|
||||
{
|
||||
uint32_t val;
|
||||
int rval;
|
||||
|
||||
if (qla_flash_write_enable(ha) != 0)
|
||||
return(-1);
|
||||
|
||||
val = start;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
|
||||
|
||||
val = 3;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
|
||||
|
||||
val = ROM_OPCODE_SECTOR_ERASE;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
|
||||
|
||||
rval = qla_wait_for_flash_busy(ha);
|
||||
|
||||
if (rval)
|
||||
device_printf(ha->pci_dev, "%s: failed \n", __func__);
|
||||
return rval;
|
||||
}
|
||||
|
||||
#define Q8_FLASH_SECTOR_SIZE 0x10000
|
||||
int
|
||||
qla_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size)
|
||||
{
|
||||
int rval = 0;
|
||||
uint32_t start;
|
||||
|
||||
if (off & (Q8_FLASH_SECTOR_SIZE -1))
|
||||
return -1;
|
||||
|
||||
if ((rval = qla_p3p_sem_lock2(ha)))
|
||||
goto qla_erase_flash_exit;
|
||||
|
||||
if ((rval = qla_flash_unprotect(ha)))
|
||||
goto qla_erase_flash_unlock_exit;
|
||||
|
||||
if ((rval = qla_wait_for_flash_unprotect(ha)))
|
||||
goto qla_erase_flash_unlock_exit;
|
||||
|
||||
for (start = off; start < (off + size); start = start + 0x10000) {
|
||||
if (qla_erase_flash_sector(ha, start)) {
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rval = qla_flash_protect(ha);
|
||||
|
||||
qla_erase_flash_unlock_exit:
|
||||
qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
|
||||
|
||||
qla_erase_flash_exit:
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static int
|
||||
qla_flash_write32(qla_host_t *ha, uint32_t off, uint32_t data)
|
||||
{
|
||||
uint32_t val;
|
||||
int rval = 0;
|
||||
|
||||
val = data;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
|
||||
|
||||
val = off;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
|
||||
|
||||
val = 3;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
|
||||
|
||||
val = ROM_OPCODE_PROG_PAGE;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
|
||||
|
||||
rval = qla_wait_for_flash_busy(ha);
|
||||
|
||||
if (rval)
|
||||
device_printf(ha->pci_dev, "%s: failed \n", __func__);
|
||||
|
||||
return rval;
|
||||
}
|
||||
|
||||
static int
|
||||
qla_flash_wait_for_write_complete(qla_host_t *ha)
|
||||
{
|
||||
uint32_t val, count = 1000;
|
||||
int rval = 0;
|
||||
|
||||
while (count--) {
|
||||
|
||||
val = 0;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
|
||||
|
||||
val = ROM_OPCODE_RD_STATUS_REG;
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
|
||||
|
||||
|
||||
rval = qla_wait_for_flash_busy(ha);
|
||||
|
||||
if (rval == 0) {
|
||||
qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
|
||||
|
||||
if ((val & BIT_0) == 0)
|
||||
return (0);
|
||||
}
|
||||
qla_mdelay(__func__, 1);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
qla_flash_write(qla_host_t *ha, uint32_t off, uint32_t data)
|
||||
{
|
||||
if (qla_flash_write_enable(ha) != 0)
|
||||
return(-1);
|
||||
|
||||
if (qla_flash_write32(ha, off, data) != 0)
|
||||
return -1;
|
||||
|
||||
if (qla_flash_wait_for_write_complete(ha))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
qla_flash_write_pattern(qla_host_t *ha, uint32_t off, uint32_t size,
|
||||
uint32_t pattern)
|
||||
{
|
||||
int rval = 0;
|
||||
uint32_t start;
|
||||
|
||||
|
||||
if ((rval = qla_p3p_sem_lock2(ha)))
|
||||
goto qla_wr_pattern_exit;
|
||||
|
||||
if ((rval = qla_flash_unprotect(ha)))
|
||||
goto qla_wr_pattern_unlock_exit;
|
||||
|
||||
if ((rval = qla_wait_for_flash_unprotect(ha)))
|
||||
goto qla_wr_pattern_unlock_exit;
|
||||
|
||||
for (start = off; start < (off + size); start = start + 4) {
|
||||
if (qla_flash_write(ha, start, pattern)) {
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rval = qla_flash_protect(ha);
|
||||
|
||||
if (rval == 0)
|
||||
rval = qla_wait_for_flash_protect(ha);
|
||||
|
||||
qla_wr_pattern_unlock_exit:
|
||||
qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
|
||||
|
||||
qla_wr_pattern_exit:
|
||||
return (rval);
|
||||
}
|
||||
|
||||
static int
|
||||
qla_flash_write_data(qla_host_t *ha, uint32_t off, uint32_t size,
|
||||
void *data)
|
||||
{
|
||||
int rval = 0;
|
||||
uint32_t start;
|
||||
uint32_t *data32 = data;
|
||||
|
||||
|
||||
if ((rval = qla_p3p_sem_lock2(ha)))
|
||||
goto qla_wr_pattern_exit;
|
||||
|
||||
if ((rval = qla_flash_unprotect(ha)))
|
||||
goto qla_wr_pattern_unlock_exit;
|
||||
|
||||
if ((rval = qla_wait_for_flash_unprotect(ha)))
|
||||
goto qla_wr_pattern_unlock_exit;
|
||||
|
||||
for (start = off; start < (off + size); start = start + 4) {
|
||||
|
||||
if (*data32 != 0xFFFFFFFF) {
|
||||
if (qla_flash_write(ha, start, *data32)) {
|
||||
rval = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
data32++;
|
||||
}
|
||||
|
||||
rval = qla_flash_protect(ha);
|
||||
|
||||
if (rval == 0)
|
||||
rval = qla_wait_for_flash_protect(ha);
|
||||
|
||||
qla_wr_pattern_unlock_exit:
|
||||
qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
|
||||
|
||||
qla_wr_pattern_exit:
|
||||
return (rval);
|
||||
}
|
||||
|
||||
int
|
||||
qla_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size, void *buf,
|
||||
uint32_t pattern)
|
||||
{
|
||||
int rval = 0;
|
||||
void *data;
|
||||
|
||||
|
||||
if (size == 0)
|
||||
return 0;
|
||||
|
||||
size = size << 2;
|
||||
|
||||
if (buf == NULL) {
|
||||
rval = qla_flash_write_pattern(ha, off, size, pattern);
|
||||
return (rval);
|
||||
}
|
||||
|
||||
if ((data = malloc(size, M_QLA8XXXBUF, M_NOWAIT)) == NULL) {
|
||||
device_printf(ha->pci_dev, "%s: malloc failed \n", __func__);
|
||||
rval = -1;
|
||||
goto qla_wr_flash_buffer_exit;
|
||||
}
|
||||
|
||||
if ((rval = copyin(buf, data, size))) {
|
||||
device_printf(ha->pci_dev, "%s copyin failed\n", __func__);
|
||||
goto qla_wr_flash_buffer_free_exit;
|
||||
}
|
||||
|
||||
rval = qla_flash_write_data(ha, off, size, data);
|
||||
|
||||
qla_wr_flash_buffer_free_exit:
|
||||
free(data, M_QLA8XXXBUF);
|
||||
|
||||
qla_wr_flash_buffer_exit:
|
||||
return (rval);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -154,6 +154,11 @@ qla_add_sysctls(qla_host_t *ha)
|
||||
(void *)ha, 0,
|
||||
qla_sysctl_get_stats, "I", "Statistics");
|
||||
|
||||
SYSCTL_ADD_STRING(device_get_sysctl_ctx(dev),
|
||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
|
||||
OID_AUTO, "fw_version", CTLFLAG_RD,
|
||||
&ha->fw_ver_str, 0, "firmware version");
|
||||
|
||||
dbg_level = 0;
|
||||
SYSCTL_ADD_UINT(device_get_sysctl_ctx(dev),
|
||||
SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
|
||||
@ -347,6 +352,10 @@ qla_pci_attach(device_t dev)
|
||||
ha->fw_ver_major, ha->fw_ver_minor, ha->fw_ver_sub,
|
||||
ha->fw_ver_build);
|
||||
|
||||
snprintf(ha->fw_ver_str, sizeof(ha->fw_ver_str), "%d.%d.%d.%d",
|
||||
ha->fw_ver_major, ha->fw_ver_minor, ha->fw_ver_sub,
|
||||
ha->fw_ver_build);
|
||||
|
||||
//qla_get_hw_caps(ha);
|
||||
qla_read_mac_addr(ha);
|
||||
|
||||
@ -660,6 +669,7 @@ qla_init_ifnet(device_t dev, qla_host_t *ha)
|
||||
|
||||
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
|
||||
|
||||
ifp->if_mtu = ETHERMTU;
|
||||
ifp->if_baudrate = (1 * 1000 * 1000 *1000);
|
||||
ifp->if_init = qla_init;
|
||||
ifp->if_softc = ha;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -201,6 +201,10 @@
|
||||
*/
|
||||
|
||||
#define Q8_ROM_RD_DATA 0x03310018
|
||||
#define Q8_ROM_WR_DATA 0x0331000C
|
||||
#define Q8_ROM_DIRECT_WINDOW 0x03310030
|
||||
#define Q8_ROM_DIRECT_DATA_OFFSET 0x03310000
|
||||
|
||||
|
||||
#define Q8_NX_CDRP_CMD_RSP 0x1B2218
|
||||
#define Q8_NX_CDRP_ARG1 0x1B221C
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2010-2011 Qlogic Corporation
|
||||
* Copyright (c) 2011-2013 Qlogic Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -36,6 +36,6 @@
|
||||
|
||||
#define QLA_VERSION_MAJOR 1
|
||||
#define QLA_VERSION_MINOR 1
|
||||
#define QLA_VERSION_BUILD 30
|
||||
#define QLA_VERSION_BUILD 36
|
||||
|
||||
#endif /* #ifndef _QLA_VER_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user