diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2004-11-18 21:02:43 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2004-11-18 21:02:43 +0000 |
commit | 5202f3110eef90c0443d32c4807f9295dd358661 (patch) | |
tree | 9e89fb5e546fe566b6960663afe8c06bec9e2402 | |
parent | 7d254a13bfe6b946843ade9d4283f4a7072db0d5 (diff) |
use the filesystem based firmware loader; deraadt ok
-rw-r--r-- | sbin/ipwcontrol/ipwcontrol.8 | 25 | ||||
-rw-r--r-- | sbin/ipwcontrol/ipwcontrol.c | 54 | ||||
-rw-r--r-- | share/man/man4/ipw.4 | 11 | ||||
-rw-r--r-- | sys/dev/pci/files.pci | 4 | ||||
-rw-r--r-- | sys/dev/pci/if_ipw.c | 142 | ||||
-rw-r--r-- | sys/dev/pci/if_ipwvar.h | 17 |
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) |