summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--share/man/man4/wpi.49
-rw-r--r--sys/dev/pci/if_wpi.c187
-rw-r--r--sys/dev/pci/if_wpireg.h25
3 files changed, 112 insertions, 109 deletions
diff --git a/share/man/man4/wpi.4 b/share/man/man4/wpi.4
index fbb61130d21..a4524e691e1 100644
--- a/share/man/man4/wpi.4
+++ b/share/man/man4/wpi.4
@@ -1,4 +1,4 @@
-.\" $OpenBSD: wpi.4,v 1.11 2007/06/06 18:17:14 damien Exp $
+.\" $OpenBSD: wpi.4,v 1.12 2007/07/10 18:29:38 damien Exp $
.\"
.\" Copyright (c) 2006, 2007
.\" Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
@@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd $Mdocdate: June 6 2007 $
+.Dd $Mdocdate: July 10 2007 $
.Os
.Dt WPI 4
.Sh NAME
@@ -70,6 +70,7 @@ sole mechanism to secure wireless communication.
WEP is not enabled by default.
.Pp
The device has one temperature sensor.
+Its value is in the range from 0 (coolest) to 285 (warmest).
Sensor data is updated every 500 milliseconds.
.Sh CONFIGURATION
The
@@ -176,7 +177,7 @@ Disable WEP encryption.
This is the default mode of operation.
.El
.Sh FILES
-The driver needs at least version 2.14.3 of the following firmware file,
+The driver needs at least version 2.14.4 of the following firmware file,
which is loaded when an interface is brought up:
.Pp
.Bl -tag -width Ds -offset indent -compact
@@ -196,7 +197,7 @@ A prepackaged version of the firmware, designed to be used with
.Xr pkg_add 1 ,
can be found at:
.Pp
-.Pa http://damien.bergamini.free.fr/packages/openbsd/wpi-firmware-2.14.3.tgz
+.Pa http://damien.bergamini.free.fr/packages/openbsd/wpi-firmware-2.14.4.tgz
.Sh EXAMPLES
The following
.Xr hostname.if 5
diff --git a/sys/dev/pci/if_wpi.c b/sys/dev/pci/if_wpi.c
index cd7958f82cf..17aeb24f0b6 100644
--- a/sys/dev/pci/if_wpi.c
+++ b/sys/dev/pci/if_wpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wpi.c,v 1.46 2007/07/05 20:29:22 damien Exp $ */
+/* $OpenBSD: if_wpi.c,v 1.47 2007/07/10 18:29:38 damien Exp $ */
/*-
* Copyright (c) 2006, 2007
@@ -100,9 +100,10 @@ void wpi_mem_lock(struct wpi_softc *);
void wpi_mem_unlock(struct wpi_softc *);
uint32_t wpi_mem_read(struct wpi_softc *, uint16_t);
void wpi_mem_write(struct wpi_softc *, uint16_t, uint32_t);
+void wpi_mem_write_region_4(struct wpi_softc *, uint16_t,
+ const uint32_t *, int);
int wpi_read_prom_data(struct wpi_softc *, uint32_t, void *, int);
-int wpi_load_segment(struct wpi_softc *, uint32_t, const uint8_t *,
- int);
+int wpi_load_microcode(struct wpi_softc *, const uint8_t *, int);
int wpi_load_firmware(struct wpi_softc *);
void wpi_calib_timeout(void *);
void wpi_iter_func(void *, struct ieee80211_node *);
@@ -536,8 +537,7 @@ wpi_alloc_rx_ring(struct wpi_softc *sc, struct wpi_rx_ring *ring)
ring->cur = 0;
error = wpi_dma_contig_alloc(sc->sc_dmat, &ring->desc_dma,
- (void **)&ring->desc,
- WPI_RX_RING_COUNT * sizeof (struct wpi_rx_desc),
+ (void **)&ring->desc, WPI_RX_RING_COUNT * sizeof (uint32_t),
WPI_RING_DMA_ALIGN, BUS_DMA_NOWAIT);
if (error != 0) {
printf("%s: could not allocate rx ring DMA memory\n",
@@ -917,6 +917,14 @@ wpi_mem_write(struct wpi_softc *sc, uint16_t addr, uint32_t data)
WPI_WRITE(sc, WPI_WRITE_MEM_DATA, data);
}
+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.
@@ -952,71 +960,65 @@ wpi_read_prom_data(struct wpi_softc *sc, uint32_t addr, void *data, int len)
return 0;
}
+/*
+ * The firmware boot code is small and is intended to be copied directly into
+ * the NIC internal memory.
+ */
int
-wpi_load_segment(struct wpi_softc *sc, uint32_t target, const uint8_t *data,
- int len)
+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;
-
- DPRINTFN(2, ("loading firmware segment target=%x len=%d\n", target,
- len));
-
- /* 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);
+ int ntries;
- /* 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);
+ size /= sizeof (uint32_t);
- /* tell adapter where to copy data in its internal memory */
- WPI_WRITE(sc, WPI_FW_TARGET, target);
+ wpi_mem_lock(sc);
- WPI_WRITE(sc, WPI_TX_CONFIG(6), 0);
+ /* copy microcode image into NIC memory */
+ wpi_mem_write_region_4(sc, WPI_MEM_UCODE_BASE,
+ (const uint32_t *)ucode, size);
- /* copy Tx descriptor into NIC memory */
- WPI_WRITE_REGION_4(sc, WPI_TX_DESC(6), (uint32_t *)&desc,
- sizeof desc / sizeof (uint32_t));
+ 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_CREDIT(6), 0xfffff);
- WPI_WRITE(sc, WPI_TX_STATE(6), 0x4001);
- WPI_WRITE(sc, WPI_TX_CONFIG(6), 0x80000001);
+ /* run microcode */
+ wpi_mem_write(sc, WPI_MEM_UCODE_CTL, WPI_UC_RUN);
- /* wait while the adapter transfers the segment */
- 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) {
- printf("%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;
}
+
int
wpi_load_firmware(struct wpi_softc *sc)
{
struct wpi_dma_info *dma = &sc->fw_dma;
const 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;
u_char *fw;
size_t size;
- uint32_t tmp;
int error;
/* load firmware image from disk */
- if ((error = loadfirmware("wpi-ucode", &fw, &size)) != 0) {
+ if ((error = loadfirmware("wpi-3945abg", &fw, &size)) != 0) {
printf("%s: could not read firmware file\n",
sc->sc_dev.dv_xname);
goto fail1;
@@ -1032,38 +1034,25 @@ wpi_load_firmware(struct wpi_softc *sc)
hdr = (const struct wpi_firmware_hdr *)fw;
main_textsz = letoh32(hdr->main_textsz);
main_datasz = letoh32(hdr->main_datasz);
+ init_textsz = htole32(hdr->init_textsz);
+ init_datasz = htole32(hdr->init_datasz);
boot_textsz = letoh32(hdr->boot_textsz);
- boot_datasz = letoh32(hdr->boot_datasz);
- /* sanity-check firmware header */
- if (main_textsz > WPI_FW_MAIN_TEXT_MAXSZ) {
- printf("%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) {
- printf("%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) {
- printf("%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) {
- printf("%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) {
printf("%s: firmware file too short: %d bytes\n",
sc->sc_dev.dv_xname, size);
error = EINVAL;
@@ -1073,45 +1062,55 @@ wpi_load_firmware(struct wpi_softc *sc)
/* get pointers to firmware segments */
main_text = (const uint8_t *)(hdr + 1);
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) {
- printf("%s: could not load firmware boot .data segment\n",
+ /* copy initialization images into pre-allocated DMA-safe memory */
+ memcpy(dma->vaddr, init_data, init_datasz);
+ memcpy(dma->vaddr + WPI_FW_INIT_DATA_MAXSZ, init_text, init_textsz);
+
+ /* tell adapter where to find initialization images */
+ wpi_mem_lock(sc);
+ 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 fail2;
}
- /* load firmware boot .text segment into NIC */
- error = wpi_load_segment(sc, WPI_FW_TEXT, boot_text, boot_textsz);
- if (error != 0) {
- printf("%s: could not load firmware boot .text segment\n",
+ /* now press "execute" ;-) */
+ WPI_WRITE(sc, WPI_RESET, 0);
+
+ /* wait at most one second for first 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);
goto fail2;
}
- /* copy firmware runtime into pre-allocated DMA-safe memory */
- memcpy(dma->vaddr, main_text, main_textsz);
- memcpy(dma->vaddr + main_textsz, main_data, main_datasz);
- bus_dmamap_sync(dma->tag, dma->map, 0, main_textsz + main_datasz,
- BUS_DMASYNC_PREWRITE);
+ /* copy runtime images into pre-allocated DMA-safe memory */
+ memcpy(dma->vaddr, main_data, main_datasz);
+ memcpy(dma->vaddr + WPI_FW_MAIN_DATA_MAXSZ, main_text, main_textsz);
- /* tell adapter where to find firmware runtime */
+ /* tell adapter where to find runtime 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, 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);
- /* 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);
-
- /* ..and wait at most one second for adapter to initialize */
+ /* 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",
diff --git a/sys/dev/pci/if_wpireg.h b/sys/dev/pci/if_wpireg.h
index 9945d897ff6..110bac8c735 100644
--- a/sys/dev/pci/if_wpireg.h
+++ b/sys/dev/pci/if_wpireg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_wpireg.h,v 1.15 2007/06/16 14:15:37 damien Exp $ */
+/* $OpenBSD: if_wpireg.h,v 1.16 2007/07/10 18:29:38 damien Exp $ */
/*-
* Copyright (c) 2006, 2007
@@ -49,7 +49,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
@@ -92,10 +91,10 @@
#define WPI_MEM_UCODE_SIZE 0x340c
#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 */
@@ -108,9 +107,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)
@@ -143,7 +141,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)
@@ -571,14 +570,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;
} __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.