change firmware loading code to adopt the new 2.14.4 firmware layout (from
OpenBSD). While here, remove some dead code I added when I ported the code from OpenBSD. IMPORTANT : You must download the 2.14.4 firmware or update your sysutils/wpi-firmware2 to the last revision (2.14.4) or the driver will stop working.
This commit is contained in:
parent
8f80c199b2
commit
d1103dfaef
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_wpi.c,v 1.16 2007/07/11 17:51:07 degroote Exp $ */
|
||||
/* $NetBSD: if_wpi.c,v 1.17 2007/07/18 18:49:16 degroote Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006, 2007
|
||||
|
@ -18,7 +18,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.16 2007/07/11 17:51:07 degroote Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: if_wpi.c,v 1.17 2007/07/18 18:49:16 degroote Exp $");
|
||||
|
||||
/*
|
||||
* Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters.
|
||||
|
@ -121,9 +121,10 @@ static void wpi_mem_lock(struct wpi_softc *);
|
|||
static void wpi_mem_unlock(struct wpi_softc *);
|
||||
static uint32_t wpi_mem_read(struct wpi_softc *, uint16_t);
|
||||
static void wpi_mem_write(struct wpi_softc *, uint16_t, uint32_t);
|
||||
static void wpi_mem_write_region_4(struct wpi_softc *, uint16_t,
|
||||
const uint32_t *, int);
|
||||
static int wpi_read_prom_data(struct wpi_softc *, uint32_t, void *, int);
|
||||
static int wpi_load_segment(struct wpi_softc *, uint32_t, const uint8_t *,
|
||||
int);
|
||||
static int wpi_load_microcode(struct wpi_softc *, const uint8_t *, int);
|
||||
static int wpi_load_firmware(struct wpi_softc *);
|
||||
static void wpi_calib_timeout(void *);
|
||||
static void wpi_iter_func(void *, struct ieee80211_node *);
|
||||
|
@ -1036,6 +1037,15 @@ wpi_mem_write(struct wpi_softc *sc, uint16_t addr, uint32_t data)
|
|||
WPI_WRITE(sc, WPI_WRITE_MEM_DATA, data);
|
||||
}
|
||||
|
||||
static void
|
||||
wpi_mem_write_region_4(struct wpi_softc *sc, uint16_t addr,
|
||||
const uint32_t *data, int wlen)
|
||||
{
|
||||
for (; wlen > 0; wlen--, data++, addr += 4)
|
||||
wpi_mem_write(sc, addr, *data);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Read `len' bytes from the EEPROM. We access the EEPROM through the MAC
|
||||
* instead of using the traditional bit-bang method.
|
||||
|
@ -1071,55 +1081,47 @@ wpi_read_prom_data(struct wpi_softc *sc, uint32_t addr, void *data, int len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
wpi_load_segment(struct wpi_softc *sc, uint32_t target, const uint8_t *data,
|
||||
int len)
|
||||
/*
|
||||
* The firmware boot code is small and is intended to be copied directly into
|
||||
* the NIC internal memory.
|
||||
*/
|
||||
int
|
||||
wpi_load_microcode(struct wpi_softc *sc, const uint8_t *ucode, int size)
|
||||
{
|
||||
struct wpi_dma_info *dma = &sc->fw_dma;
|
||||
struct wpi_tx_desc desc;
|
||||
int ntries, error = 0;
|
||||
int ntries;
|
||||
|
||||
DPRINTFN(2, ("loading firmware segment target=%x len=%d\n", target,
|
||||
len));
|
||||
size /= sizeof (uint32_t);
|
||||
|
||||
/* copy data to pre-allocated DMA-safe memory */
|
||||
memcpy(dma->vaddr, data, len);
|
||||
bus_dmamap_sync(dma->tag, dma->map, 0, len, BUS_DMASYNC_PREWRITE);
|
||||
wpi_mem_lock(sc);
|
||||
|
||||
/* setup Tx descriptor */
|
||||
memset(&desc, 0, sizeof desc);
|
||||
desc.flags = htole32(WPI_PAD32(len) << 28 | 1 << 24);
|
||||
desc.segs[0].addr = htole32(dma->paddr);
|
||||
desc.segs[0].len = htole32(len);
|
||||
/* copy microcode image into NIC memory */
|
||||
wpi_mem_write_region_4(sc, WPI_MEM_UCODE_BASE,
|
||||
(const uint32_t *)ucode, size);
|
||||
|
||||
/* tell adapter where to copy data in its internal memory */
|
||||
WPI_WRITE(sc, WPI_FW_TARGET, target);
|
||||
wpi_mem_write(sc, WPI_MEM_UCODE_SRC, 0);
|
||||
wpi_mem_write(sc, WPI_MEM_UCODE_DST, WPI_FW_TEXT);
|
||||
wpi_mem_write(sc, WPI_MEM_UCODE_SIZE, size);
|
||||
|
||||
WPI_WRITE(sc, WPI_TX_CONFIG(6), 0);
|
||||
/* run microcode */
|
||||
wpi_mem_write(sc, WPI_MEM_UCODE_CTL, WPI_UC_RUN);
|
||||
|
||||
/* copy Tx descriptor into NIC memory */
|
||||
WPI_WRITE_REGION_4(sc, WPI_TX_DESC(6), (uint32_t *)&desc,
|
||||
sizeof desc / sizeof (uint32_t));
|
||||
|
||||
WPI_WRITE(sc, WPI_TX_CREDIT(6), 0xfffff);
|
||||
WPI_WRITE(sc, WPI_TX_STATE(6), 0x4001);
|
||||
WPI_WRITE(sc, WPI_TX_CONFIG(6), 0x80000001);
|
||||
|
||||
/* wait while the adapter transfers the block */
|
||||
for (ntries = 0; ntries < 100; ntries++) {
|
||||
if (WPI_READ(sc, WPI_TX_STATUS) & WPI_TX_IDLE(6))
|
||||
/* wait for transfer to complete */
|
||||
for (ntries = 0; ntries < 1000; ntries++) {
|
||||
if (!(wpi_mem_read(sc, WPI_MEM_UCODE_CTL) & WPI_UC_RUN))
|
||||
break;
|
||||
DELAY(1000);
|
||||
DELAY(10);
|
||||
}
|
||||
if (ntries == 100) {
|
||||
aprint_error("%s: timeout transferring firmware segment\n",
|
||||
if (ntries == 1000) {
|
||||
wpi_mem_unlock(sc);
|
||||
printf("%s: could not load boot firmware\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
error = ETIMEDOUT;
|
||||
return ETIMEDOUT;
|
||||
}
|
||||
wpi_mem_write(sc, WPI_MEM_UCODE_CTL, WPI_UC_ENABLE);
|
||||
|
||||
WPI_WRITE(sc, WPI_TX_CREDIT(6), 0);
|
||||
wpi_mem_unlock(sc);
|
||||
|
||||
return error;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1127,12 +1129,13 @@ wpi_load_firmware(struct wpi_softc *sc)
|
|||
{
|
||||
struct wpi_dma_info *dma = &sc->fw_dma;
|
||||
struct wpi_firmware_hdr hdr;
|
||||
const uint8_t *boot_text, *boot_data, *main_text, *main_data;
|
||||
uint32_t main_textsz, main_datasz, boot_textsz, boot_datasz;
|
||||
const uint8_t *init_text, *init_data, *main_text, *main_data;
|
||||
const uint8_t *boot_text;
|
||||
uint32_t init_textsz, init_datasz, main_textsz, main_datasz;
|
||||
uint32_t boot_textsz;
|
||||
firmware_handle_t fw;
|
||||
u_char *dfw;
|
||||
size_t size;
|
||||
uint32_t tmp;
|
||||
int error;
|
||||
|
||||
/* load firmware image from disk */
|
||||
|
@ -1161,38 +1164,25 @@ wpi_load_firmware(struct wpi_softc *sc)
|
|||
|
||||
main_textsz = le32toh(hdr.main_textsz);
|
||||
main_datasz = le32toh(hdr.main_datasz);
|
||||
init_textsz = le32toh(hdr.init_textsz);
|
||||
init_datasz = le32toh(hdr.init_datasz);
|
||||
boot_textsz = le32toh(hdr.boot_textsz);
|
||||
boot_datasz = le32toh(hdr.boot_datasz);
|
||||
|
||||
/* sanity-check firmware header */
|
||||
if (main_textsz > WPI_FW_MAIN_TEXT_MAXSZ) {
|
||||
aprint_error("%s: main .text segment too large: %u bytes\n",
|
||||
sc->sc_dev.dv_xname, main_textsz);
|
||||
error = EINVAL;
|
||||
goto fail2;
|
||||
}
|
||||
if (main_datasz > WPI_FW_MAIN_DATA_MAXSZ) {
|
||||
aprint_error("%s: main .data segment too large: %u bytes\n",
|
||||
sc->sc_dev.dv_xname, main_datasz);
|
||||
error = EINVAL;
|
||||
goto fail2;
|
||||
}
|
||||
if (boot_textsz > WPI_FW_BOOT_TEXT_MAXSZ) {
|
||||
aprint_error("%s: boot .text segment too large: %u bytes\n",
|
||||
sc->sc_dev.dv_xname, boot_textsz);
|
||||
error = EINVAL;
|
||||
goto fail2;
|
||||
}
|
||||
if (boot_datasz > WPI_FW_BOOT_DATA_MAXSZ) {
|
||||
aprint_error("%s: boot .data segment too large: %u bytes\n",
|
||||
sc->sc_dev.dv_xname, boot_datasz);
|
||||
/* sanity-check firmware segments sizes */
|
||||
if (main_textsz > WPI_FW_MAIN_TEXT_MAXSZ ||
|
||||
main_datasz > WPI_FW_MAIN_DATA_MAXSZ ||
|
||||
init_textsz > WPI_FW_INIT_TEXT_MAXSZ ||
|
||||
init_datasz > WPI_FW_INIT_DATA_MAXSZ ||
|
||||
boot_textsz > WPI_FW_BOOT_TEXT_MAXSZ ||
|
||||
(boot_textsz & 3) != 0) {
|
||||
printf("%s: invalid firmware header\n", sc->sc_dev.dv_xname);
|
||||
error = EINVAL;
|
||||
goto fail2;
|
||||
}
|
||||
|
||||
/* check that all firmware segments are present */
|
||||
if (size < sizeof (struct wpi_firmware_hdr) + main_textsz +
|
||||
main_datasz + boot_textsz + boot_datasz) {
|
||||
main_datasz + init_textsz + init_datasz + boot_textsz) {
|
||||
aprint_error("%s: firmware file too short: %zu bytes\n",
|
||||
sc->sc_dev.dv_xname, size);
|
||||
error = EINVAL;
|
||||
|
@ -1216,43 +1206,32 @@ wpi_load_firmware(struct wpi_softc *sc)
|
|||
/* get pointers to firmware segments */
|
||||
main_text = dfw + sizeof (struct wpi_firmware_hdr);
|
||||
main_data = main_text + main_textsz;
|
||||
boot_text = main_data + main_datasz;
|
||||
boot_data = boot_text + boot_textsz;
|
||||
init_text = main_data + main_datasz;
|
||||
init_data = init_text + init_textsz;
|
||||
boot_text = init_data + init_datasz;
|
||||
|
||||
/* load firmware boot .data segment into NIC */
|
||||
error = wpi_load_segment(sc, WPI_FW_DATA, boot_data, boot_datasz);
|
||||
if (error != 0) {
|
||||
aprint_error("%s: could not load firmware boot .data segment\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
goto fail3;
|
||||
}
|
||||
/* copy initialization images into pre-allocated DMA-safe memory */
|
||||
memcpy(dma->vaddr, init_data, init_datasz);
|
||||
memcpy((char*)dma->vaddr + WPI_FW_INIT_DATA_MAXSZ, init_text, init_textsz);
|
||||
|
||||
/* load firmware boot .text segment into NIC */
|
||||
error = wpi_load_segment(sc, WPI_FW_TEXT, boot_text, boot_textsz);
|
||||
if (error != 0) {
|
||||
aprint_error("%s: could not load firmware boot .text segment\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
/* copy firmware runtime into pre-allocated DMA-safe memory */
|
||||
memcpy(dma->vaddr, main_text, main_textsz);
|
||||
memcpy((uint8_t*)dma->vaddr + main_textsz, main_data, main_datasz);
|
||||
bus_dmamap_sync(dma->tag, dma->map, 0, main_textsz + main_datasz,
|
||||
BUS_DMASYNC_PREWRITE);
|
||||
|
||||
/* tell adapter where to find firmware runtime */
|
||||
/* tell adapter where to find initialization images */
|
||||
wpi_mem_lock(sc);
|
||||
wpi_mem_write(sc, WPI_MEM_MAIN_TEXT_BASE, dma->paddr);
|
||||
wpi_mem_write(sc, WPI_MEM_MAIN_TEXT_SIZE, main_textsz);
|
||||
wpi_mem_write(sc, WPI_MEM_MAIN_DATA_BASE, dma->paddr + main_textsz);
|
||||
wpi_mem_write(sc, WPI_MEM_MAIN_DATA_SIZE, main_datasz);
|
||||
wpi_mem_write(sc, WPI_MEM_DATA_BASE, dma->paddr);
|
||||
wpi_mem_write(sc, WPI_MEM_DATA_SIZE, init_datasz);
|
||||
wpi_mem_write(sc, WPI_MEM_TEXT_BASE,
|
||||
dma->paddr + WPI_FW_INIT_DATA_MAXSZ);
|
||||
wpi_mem_write(sc, WPI_MEM_TEXT_SIZE, init_textsz);
|
||||
wpi_mem_unlock(sc);
|
||||
|
||||
/* load firmware boot code */
|
||||
if ((error = wpi_load_microcode(sc, boot_text, boot_textsz)) != 0) {
|
||||
printf("%s: could not load boot firmware\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
goto fail3;
|
||||
}
|
||||
|
||||
/* now press "execute" ;-) */
|
||||
tmp = WPI_READ(sc, WPI_RESET);
|
||||
tmp &= ~(WPI_MASTER_DISABLED | WPI_STOP_MASTER | WPI_NEVO_RESET);
|
||||
WPI_WRITE(sc, WPI_RESET, tmp);
|
||||
WPI_WRITE(sc, WPI_RESET, 0);
|
||||
|
||||
/* ..and wait at most one second for adapter to initialize */
|
||||
if ((error = tsleep(sc, PCATCH, "wpiinit", hz)) != 0) {
|
||||
|
@ -1261,6 +1240,27 @@ wpi_load_firmware(struct wpi_softc *sc)
|
|||
sc->sc_dev.dv_xname);
|
||||
}
|
||||
|
||||
/* copy runtime images into pre-allocated DMA-safe memory */
|
||||
memcpy(dma->vaddr, main_data, main_datasz);
|
||||
memcpy((char*)dma->vaddr + WPI_FW_MAIN_DATA_MAXSZ, main_text, main_textsz);
|
||||
|
||||
/* tell adapter where to find runtime images */
|
||||
wpi_mem_lock(sc);
|
||||
wpi_mem_write(sc, WPI_MEM_DATA_BASE, dma->paddr);
|
||||
wpi_mem_write(sc, WPI_MEM_DATA_SIZE, main_datasz);
|
||||
wpi_mem_write(sc, WPI_MEM_TEXT_BASE,
|
||||
dma->paddr + WPI_FW_MAIN_DATA_MAXSZ);
|
||||
wpi_mem_write(sc, WPI_MEM_TEXT_SIZE, WPI_FW_UPDATED | main_textsz);
|
||||
wpi_mem_unlock(sc);
|
||||
|
||||
/* wait at most one second for second alive notification */
|
||||
if ((error = tsleep(sc, PCATCH, "wpiinit", hz)) != 0) {
|
||||
/* this isn't what was supposed to happen.. */
|
||||
printf("%s: timeout waiting for adapter to initialize\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
}
|
||||
|
||||
|
||||
fail3: firmware_free(dfw,size);
|
||||
fail2: firmware_close(fw);
|
||||
fail1: return error;
|
||||
|
@ -2696,17 +2696,9 @@ wpi_scan(struct wpi_softc *sc, uint16_t flags)
|
|||
|
||||
frm = (uint8_t *)(wh + 1);
|
||||
|
||||
#ifdef old_code
|
||||
/* add essid IE */
|
||||
*frm++ = IEEE80211_ELEMID_SSID;
|
||||
*frm++ = ic->ic_des_esslen;
|
||||
memcpy(frm, ic->ic_des_essid, ic->ic_des_esslen);
|
||||
frm += ic->ic_des_esslen;
|
||||
#else
|
||||
/* add empty essid IE (firmware generates it for directed scans) */
|
||||
*frm++ = IEEE80211_ELEMID_SSID;
|
||||
*frm++ = 0;
|
||||
#endif
|
||||
|
||||
mode = ieee80211_chan2mode(ic, ic->ic_ibss_chan);
|
||||
rs = &ic->ic_sup_rates[mode];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if_wpireg.h,v 1.4 2007/07/09 19:38:52 degroote Exp $ */
|
||||
/* $NetBSD: if_wpireg.h,v 1.5 2007/07/18 18:49:17 degroote Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006
|
||||
|
@ -52,7 +52,6 @@
|
|||
#define WPI_TEMPERATURE 0x060
|
||||
#define WPI_CHICKEN 0x100
|
||||
#define WPI_PLL_CTL 0x20c
|
||||
#define WPI_FW_TARGET 0x410
|
||||
#define WPI_WRITE_MEM_ADDR 0x444
|
||||
#define WPI_READ_MEM_ADDR 0x448
|
||||
#define WPI_WRITE_MEM_DATA 0x44c
|
||||
|
@ -96,10 +95,10 @@
|
|||
#define WPI_MEM_UCODE_BASE 0x3800
|
||||
|
||||
|
||||
#define WPI_MEM_MAIN_TEXT_BASE 0x3490
|
||||
#define WPI_MEM_MAIN_TEXT_SIZE 0x3494
|
||||
#define WPI_MEM_MAIN_DATA_BASE 0x3498
|
||||
#define WPI_MEM_MAIN_DATA_SIZE 0x349c
|
||||
#define WPI_MEM_TEXT_BASE 0x3490
|
||||
#define WPI_MEM_TEXT_SIZE 0x3494
|
||||
#define WPI_MEM_DATA_BASE 0x3498
|
||||
#define WPI_MEM_DATA_SIZE 0x349c
|
||||
|
||||
/* possible flags for register WPI_HWCONFIG */
|
||||
#define WPI_HW_ALM_MB (1 << 8)
|
||||
|
@ -111,9 +110,8 @@
|
|||
/* possible flags for registers WPI_READ_MEM_ADDR/WPI_WRITE_MEM_ADDR */
|
||||
#define WPI_MEM_4 ((sizeof (uint32_t) - 1) << 24)
|
||||
|
||||
/* possible values for WPI_FW_TARGET */
|
||||
/* possible values for WPI_MEM_UCODE_DST */
|
||||
#define WPI_FW_TEXT 0x00000000
|
||||
#define WPI_FW_DATA 0x00800000
|
||||
|
||||
/* possible flags for WPI_GPIO_STATUS */
|
||||
#define WPI_POWERED (1 << 9)
|
||||
|
@ -146,7 +144,8 @@
|
|||
#define WPI_RX_IDLE (1 << 24)
|
||||
|
||||
/* possible flags for register WPI_UC_CTL */
|
||||
#define WPI_UC_RUN (1 << 30)
|
||||
#define WPI_UC_ENABLE (1 << 30)
|
||||
#define WPI_UC_RUN (1 << 31)
|
||||
|
||||
/* possible flags for register WPI_INTR_CSR */
|
||||
#define WPI_ALIVE_INTR (1 << 0)
|
||||
|
@ -588,15 +587,18 @@ struct wpi_firmware_hdr {
|
|||
uint32_t version;
|
||||
uint32_t main_textsz;
|
||||
uint32_t main_datasz;
|
||||
uint32_t init_textsz;
|
||||
uint32_t init_datasz;
|
||||
uint32_t boot_textsz;
|
||||
uint32_t boot_datasz;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
#define WPI_FW_MAIN_TEXT_MAXSZ (80 * 1024)
|
||||
#define WPI_FW_MAIN_DATA_MAXSZ (32 * 1024)
|
||||
#define WPI_FW_INIT_TEXT_MAXSZ (80 * 1024)
|
||||
#define WPI_FW_INIT_DATA_MAXSZ (32 * 1024)
|
||||
#define WPI_FW_BOOT_TEXT_MAXSZ (80 * 1024)
|
||||
#define WPI_FW_BOOT_DATA_MAXSZ (32 * 1024)
|
||||
|
||||
#define WPI_FW_UPDATED (1 << 31)
|
||||
/*
|
||||
+ * Offsets into EEPROM.
|
||||
+ */
|
||||
|
|
Loading…
Reference in New Issue