summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2004-11-18 21:02:43 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2004-11-18 21:02:43 +0000
commit5202f3110eef90c0443d32c4807f9295dd358661 (patch)
tree9e89fb5e546fe566b6960663afe8c06bec9e2402
parent7d254a13bfe6b946843ade9d4283f4a7072db0d5 (diff)
use the filesystem based firmware loader; deraadt ok
-rw-r--r--sbin/ipwcontrol/ipwcontrol.825
-rw-r--r--sbin/ipwcontrol/ipwcontrol.c54
-rw-r--r--share/man/man4/ipw.411
-rw-r--r--sys/dev/pci/files.pci4
-rw-r--r--sys/dev/pci/if_ipw.c142
-rw-r--r--sys/dev/pci/if_ipwvar.h17
6 files changed, 82 insertions, 171 deletions
diff --git a/sbin/ipwcontrol/ipwcontrol.8 b/sbin/ipwcontrol/ipwcontrol.8
index 78f02ccfb8b..e2afecf0165 100644
--- a/sbin/ipwcontrol/ipwcontrol.8
+++ b/sbin/ipwcontrol/ipwcontrol.8
@@ -1,4 +1,4 @@
-.\" $Id: ipwcontrol.8,v 1.2 2004/10/20 21:01:38 deraadt Exp $
+.\" $Id: ipwcontrol.8,v 1.3 2004/11/18 21:02:31 damien Exp $
.\"
.\" Copyright (c) 2004
.\" Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
@@ -34,8 +34,6 @@
.Sh SYNOPSIS
.Nm
.Op Fl i Ar interface
-.Op Fl f Ar firmware
-.Op Fl k
.Op Fl r
.Sh DESCRIPTION
The
@@ -54,30 +52,9 @@ The options are as follows:
.Bl -tag -width indent
.It Fl i Ar interface
Display adapter's internal statistics.
-.It Fl f Ar firmware
-Download firmware binary image
-.Ar firmware
-to the driver.
-.It Fl k
-Kill (remove) the firmware and reset the adapter.
.It Fl r
Display the radio switch state (on or off).
.El
-.Sh FILES
-The firmware is not shipped with OpenBSD; install the
-.Pa ipw-firmware
-package.
-The original archive is available from Intel at:
-.Pa http://ipw2100.sourceforge.net/firmware.php?fid=3 .
-.Pp
-.Bl -tag -width ipw2100-1.2-i.fw -compact
-.It Pa ipw2100-1.2.fw
-BSS mode (connection to an access point) firmware
-.It Pa ipw2100-1.2-i.fw
-IBSS mode (point-to-point connection) firmware
-.It Pa ipw2100-1.2-p.fw
-Monitor mode firmware
-.El
.Sh SEE ALSO
.Xr ipw 4 ,
.Xr ifconfig 8
diff --git a/sbin/ipwcontrol/ipwcontrol.c b/sbin/ipwcontrol/ipwcontrol.c
index 13b2aef9684..acb1ff6fece 100644
--- a/sbin/ipwcontrol/ipwcontrol.c
+++ b/sbin/ipwcontrol/ipwcontrol.c
@@ -1,4 +1,4 @@
-/* $Id: ipwcontrol.c,v 1.6 2004/11/03 17:40:49 damien Exp $ */
+/* $Id: ipwcontrol.c,v 1.7 2004/11/18 21:02:32 damien Exp $ */
/*-
* Copyright (c) 2004
@@ -28,14 +28,12 @@
*/
#ifndef lint
-static char rcsid[] = "$Id: ipwcontrol.c,v 1.6 2004/11/03 17:40:49 damien Exp $";
+static char rcsid[] = "$Id: ipwcontrol.c,v 1.7 2004/11/18 21:02:32 damien Exp $";
#endif /* not lint */
#include <sys/types.h>
#include <sys/ioctl.h>
-#include <sys/mman.h>
#include <sys/socket.h>
-#include <sys/stat.h>
#include <net/if.h>
@@ -48,8 +46,6 @@ static char rcsid[] = "$Id: ipwcontrol.c,v 1.6 2004/11/03 17:40:49 damien Exp $"
#include <sysexits.h>
#include <unistd.h>
-#define SIOCSLOADFW _IOW('i', 137, struct ifreq)
-#define SIOCSKILLFW _IOW('i', 138, struct ifreq)
#define SIOCGRADIO _IOWR('i', 139, struct ifreq)
#define SIOCGTABLE1 _IOWR('i', 140, struct ifreq)
@@ -58,8 +54,6 @@ extern int optind;
static void usage(void);
static int do_req(char *, unsigned long, void *);
-static void load_firmware(char *, char *);
-static void kill_firmware(char *);
static void get_radio_state(char *);
static void get_statistics(char *);
@@ -76,21 +70,13 @@ main(int argc, char **argv)
optind = 2;
}
- while ((ch = getopt(argc, argv, "hf:i:kr")) != -1) {
+ while ((ch = getopt(argc, argv, "hi:r")) != -1) {
switch (ch) {
case 'i':
if (!ifspecified)
iface = optarg;
break;
- case 'f':
- load_firmware(iface, optarg);
- return EX_OK;
-
- case 'k':
- kill_firmware(iface);
- return EX_OK;
-
case 'r':
get_radio_state(iface);
return EX_OK;
@@ -111,9 +97,7 @@ usage(void)
{
extern char *__progname;
- fprintf(stderr,
- "usage: %s [interface] [-f firmware] [-kr]\n",
- __progname);
+ fprintf(stderr, "usage: %s [interface] [-r]\n", __progname);
exit(EX_USAGE);
}
@@ -139,36 +123,6 @@ do_req(char *iface, unsigned long req, void *data)
}
static void
-load_firmware(char *iface, char *firmware)
-{
- int fd;
- struct stat st;
- void *map;
-
- if ((fd = open(firmware, O_RDONLY)) == -1)
- err(EX_OSERR, "%s", firmware);
-
- if (fstat(fd, &st) == -1)
- err(EX_OSERR, "Unable to stat %s", firmware);
-
- if ((map = mmap(NULL, st.st_size, PROT_READ, 0, fd, 0)) == NULL)
- err(EX_OSERR, "Can't map %s into memory", firmware);
-
- if (do_req(iface, SIOCSLOADFW, map) == -1)
- err(EX_OSERR, "Can't load %s to driver", firmware);
-
- (void)munmap(map, st.st_size);
- (void)close(fd);
-}
-
-static void
-kill_firmware(char *iface)
-{
- if (do_req(iface, SIOCSKILLFW, NULL) == -1)
- err(EX_OSERR, "Can't kill firmware");
-}
-
-static void
get_radio_state(char *iface)
{
int radio;
diff --git a/share/man/man4/ipw.4 b/share/man/man4/ipw.4
index 0b79ab621bc..3520fe5c764 100644
--- a/share/man/man4/ipw.4
+++ b/share/man/man4/ipw.4
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ipw.4,v 1.5 2004/11/08 23:05:42 deraadt Exp $
+.\" $OpenBSD: ipw.4,v 1.6 2004/11/18 21:02:38 damien Exp $
.\"
.\" Copyright (c) 2004
.\" Damien Bergamini <damien.bergamini@free.fr>. All rights reserved.
@@ -50,6 +50,15 @@ This mode requires the use of an access point.
.Pp
For more information on configuring this device, see
.Xr ifconfig 8 .
+.Sh FILES
+The driver needs a couple of firmware files which are loaded on demand.
+.Pp
+.Bl -tag -width Ds -offset indent -compact
+.It Pa /etc/firmware/ipw-license
+.It Pa /etc/firmware/ipw-bss
+.It Pa /etc/firmware/ipw-ibss
+.It Pa /etc/firmware/ipw-monitor
+.El
.Sh EXAMPLES
Join an existing BSS network (ie: connect to an access point):
.Pp
diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci
index 01bcba8a9e4..05a5563b711 100644
--- a/sys/dev/pci/files.pci
+++ b/sys/dev/pci/files.pci
@@ -1,4 +1,4 @@
-# $OpenBSD: files.pci,v 1.161 2004/11/02 02:45:37 reyk Exp $
+# $OpenBSD: files.pci,v 1.162 2004/11/18 21:02:42 damien Exp $
# $NetBSD: files.pci,v 1.20 1996/09/24 17:47:15 christos Exp $
#
# Config file and device description for machine-independent PCI code.
@@ -421,7 +421,7 @@ attach an at pci with an_pci
file dev/pci/if_an_pci.c an_pci
# Intel PRO/Wireless 2100
-device ipw: ifnet, wlan
+device ipw: ifnet, wlan, firmload
attach ipw at pci
file dev/pci/if_ipw.c ipw
diff --git a/sys/dev/pci/if_ipw.c b/sys/dev/pci/if_ipw.c
index 8bbfef92621..8d52f01f414 100644
--- a/sys/dev/pci/if_ipw.c
+++ b/sys/dev/pci/if_ipw.c
@@ -1,4 +1,4 @@
-/* $Id: if_ipw.c,v 1.24 2004/11/03 17:14:31 damien Exp $ */
+/* $Id: if_ipw.c,v 1.25 2004/11/18 21:02:42 damien Exp $ */
/*-
* Copyright (c) 2004
@@ -43,6 +43,7 @@
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/conf.h>
+#include <sys/device.h>
#include <machine/bus.h>
#include <machine/endian.h>
@@ -112,8 +113,7 @@ void ipw_stop_master(struct ipw_softc *);
int ipw_reset(struct ipw_softc *);
int ipw_load_ucode(struct ipw_softc *, u_char *, int);
int ipw_load_firmware(struct ipw_softc *, u_char *, int);
-int ipw_cache_firmware(struct ipw_softc *, void *);
-void ipw_free_firmware(struct ipw_softc *);
+int ipw_read_firmware(struct ipw_softc *, struct ipw_firmware *);
int ipw_config(struct ipw_softc *);
int ipw_init(struct ifnet *);
void ipw_stop(struct ifnet *, int);
@@ -305,7 +305,6 @@ ipw_detach(struct device* self, int flags)
ipw_stop(ifp, 1);
ipw_dmamem_stop(sc);
- ipw_free_firmware(sc);
#if NBPFILTER > 0
bpfdetach(ifp);
@@ -1087,24 +1086,6 @@ ipw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
error = ipw_get_radio(sc, (int *)ifr->ifr_data);
break;
- case SIOCSLOADFW:
- /* only super-user can do that! */
- if ((error = suser(curproc, 0)) != 0)
- break;
-
- ifr = (struct ifreq *)data;
- error = ipw_cache_firmware(sc, ifr->ifr_data);
- break;
-
- case SIOCSKILLFW:
- /* only super-user can do that! */
- if ((error = suser(curproc, 0)) != 0)
- break;
-
- ipw_stop(ifp, 1);
- ipw_free_firmware(sc);
- break;
-
case SIOCG80211AUTH:
((struct ieee80211_auth *)data)->i_authtype = sc->authmode;
break;
@@ -1667,6 +1648,8 @@ ipw_load_ucode(struct ipw_softc *sc, u_char *uc, int size)
MEM_WRITE_1(sc, 0x210000, 0x00);
MEM_WRITE_1(sc, 0x210000, 0x80);
+ free(uc, M_DEVBUF);
+
for (ntries = 0; ntries < 100; ntries++) {
if (MEM_READ_1(sc, 0x210000) & 1)
break;
@@ -1734,68 +1717,59 @@ ipw_load_firmware(struct ipw_softc *sc, u_char *fw, int size)
return 0;
}
-/*
- * Store firmware into kernel memory so we can download it when we need to,
- * e.g when the adapter wakes up from suspend mode.
- */
int
-ipw_cache_firmware(struct ipw_softc *sc, void *data)
+ipw_read_firmware(struct ipw_softc *sc, struct ipw_firmware *fw)
{
- struct ipw_firmware *fw = &sc->fw;
- struct ipw_firmware_hdr hdr;
- u_char *p = data;
+ struct ipw_firmware_hdr *hdr;
+ const char *name;
+ u_char *p;
+ size_t size;
int error;
- ipw_free_firmware(sc);
-
- if ((error = copyin(data, &hdr, sizeof hdr)) != 0)
- goto fail1;
+ switch (sc->sc_ic.ic_opmode) {
+ case IEEE80211_M_STA:
+ case IEEE80211_M_HOSTAP:
+ name = "ipw-bss";
+ break;
- fw->main_size = letoh32(hdr.main_size);
- fw->ucode_size = letoh32(hdr.ucode_size);
- p += sizeof hdr;
+ case IEEE80211_M_IBSS:
+ case IEEE80211_M_AHDEMO:
+ name = "ipw-ibss";
+ break;
- fw->main = malloc(fw->main_size, M_DEVBUF, M_NOWAIT);
- if (fw->main == NULL) {
- error = ENOMEM;
- goto fail1;
+ case IEEE80211_M_MONITOR:
+ name = "ipw-monitor";
+ break;
}
- fw->ucode = malloc(fw->ucode_size, M_DEVBUF, M_NOWAIT);
- if (fw->ucode == NULL) {
- error = ENOMEM;
- goto fail2;
+ if ((error = loadfirmware(name, &fw->data, &size)) != 0)
+ return error;
+
+ if (size < sizeof (struct ipw_firmware_hdr)) {
+ error = EINVAL;
+ goto fail;
}
- if ((error = copyin(p, fw->main, fw->main_size)) != 0)
- goto fail3;
+ p = fw->data;
+ hdr = (struct ipw_firmware_hdr *)p;
+ fw->main_size = letoh32(hdr->main_size);
+ fw->ucode_size = letoh32(hdr->ucode_size);
- p += fw->main_size;
- if ((error = copyin(p, fw->ucode, fw->ucode_size)) != 0)
- goto fail3;
+ p += sizeof (struct ipw_firmware_hdr);
+ size -= sizeof (struct ipw_firmware_hdr);
- DPRINTF(("Firmware cached: main %u, ucode %u\n", fw->main_size,
- fw->ucode_size));
+ if (size < fw->main_size + fw->ucode_size) {
+ error = EINVAL;
+ goto fail;
+ }
- sc->flags |= IPW_FLAG_FW_CACHED;
+ fw->main = p;
+ fw->ucode = p + fw->main_size;
return 0;
-fail3: free(fw->ucode, M_DEVBUF);
-fail2: free(fw->main, M_DEVBUF);
-fail1: return error;
-}
-
-void
-ipw_free_firmware(struct ipw_softc *sc)
-{
- if (!(sc->flags & IPW_FLAG_FW_CACHED))
- return;
-
- free(sc->fw.main, M_DEVBUF);
- free(sc->fw.ucode, M_DEVBUF);
-
- sc->flags &= ~IPW_FLAG_FW_CACHED;
+fail: free(fw->data, M_DEVBUF);
+ return error;
}
int
@@ -2000,25 +1974,24 @@ int
ipw_init(struct ifnet *ifp)
{
struct ipw_softc *sc = ifp->if_softc;
- struct ipw_firmware *fw = &sc->fw;
+ struct ipw_firmware fw;
int error;
- /* exit immediately if firmware has not been ioctl'd */
- if (!(sc->flags & IPW_FLAG_FW_CACHED)) {
- ifp->if_flags &= ~IFF_UP;
- return EIO;
- }
-
ipw_stop(ifp, 0);
if ((error = ipw_reset(sc)) != 0) {
printf("%s: could not reset adapter\n", sc->sc_dev.dv_xname);
- goto fail;
+ goto fail1;
+ }
+
+ if ((error = ipw_read_firmware(sc, &fw)) != NULL) {
+ printf("%s: could not read firmware\n", sc->sc_dev.dv_xname);
+ goto fail1;
}
- if ((error = ipw_load_ucode(sc, fw->ucode, fw->ucode_size)) != 0) {
+ if ((error = ipw_load_ucode(sc, fw.ucode, fw.ucode_size)) != 0) {
printf("%s: could not load microcode\n", sc->sc_dev.dv_xname);
- goto fail;
+ goto fail2;
}
ipw_stop_master(sc);
@@ -2026,18 +1999,18 @@ ipw_init(struct ifnet *ifp)
if ((error = ipw_rx_init(sc)) != 0) {
printf("%s: could not initialize rx queue\n",
sc->sc_dev.dv_xname);
- goto fail;
+ goto fail2;
}
if ((error = ipw_tx_init(sc)) != 0) {
printf("%s: could not initialize tx queue\n",
sc->sc_dev.dv_xname);
- goto fail;
+ goto fail2;
}
- if ((error = ipw_load_firmware(sc, fw->main, fw->main_size)) != 0) {
+ if ((error = ipw_load_firmware(sc, fw.main, fw.main_size)) != 0) {
printf("%s: could not load firmware\n", sc->sc_dev.dv_xname);
- goto fail;
+ goto fail2;
}
sc->flags |= IPW_FLAG_FW_INITED;
@@ -2051,7 +2024,7 @@ ipw_init(struct ifnet *ifp)
if ((error = ipw_config(sc)) != 0) {
printf("%s: device configuration failed\n",
sc->sc_dev.dv_xname);
- goto fail;
+ goto fail2;
}
ifp->if_flags &= ~IFF_OACTIVE;
@@ -2059,7 +2032,8 @@ ipw_init(struct ifnet *ifp)
return 0;
-fail: ipw_stop(ifp, 0);
+fail2: free(fw.data, M_DEVBUF);
+fail1: ipw_stop(ifp, 0);
return error;
}
diff --git a/sys/dev/pci/if_ipwvar.h b/sys/dev/pci/if_ipwvar.h
index c4ca8296ea1..f389a31bf05 100644
--- a/sys/dev/pci/if_ipwvar.h
+++ b/sys/dev/pci/if_ipwvar.h
@@ -1,4 +1,4 @@
-/* $Id: if_ipwvar.h,v 1.3 2004/10/27 21:21:16 damien Exp $ */
+/* $Id: if_ipwvar.h,v 1.4 2004/11/18 21:02:42 damien Exp $ */
/*-
* Copyright (c) 2004
@@ -28,10 +28,11 @@
*/
struct ipw_firmware {
- void *main;
- int main_size;
- void *ucode;
- int ucode_size;
+ u_char *data;
+ u_char *main;
+ size_t main_size;
+ u_char *ucode;
+ size_t ucode_size;
};
struct ipw_soft_bd {
@@ -88,10 +89,8 @@ struct ipw_softc {
int (*sc_newstate)(struct ieee80211com *,
enum ieee80211_state, int);
- struct ipw_firmware fw;
u_int32_t flags;
-#define IPW_FLAG_FW_CACHED (1 << 0)
-#define IPW_FLAG_FW_INITED (1 << 1)
+#define IPW_FLAG_FW_INITED (1 << 0)
struct resource *irq;
struct resource *mem;
@@ -157,7 +156,5 @@ struct ipw_softc {
#endif
};
-#define SIOCSLOADFW _IOW('i', 137, struct ifreq)
-#define SIOCSKILLFW _IOW('i', 138, struct ifreq)
#define SIOCGRADIO _IOWR('i', 139, struct ifreq)
#define SIOCGTABLE1 _IOWR('i', 140, struct ifreq)