Use the firmload API to retrive the firmware from the filesystem.
This commit is contained in:
parent
e82413c3cf
commit
f32518359d
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: if_ipw.c,v 1.16 2005/12/24 20:27:42 perry Exp $ */
|
/* $NetBSD: if_ipw.c,v 1.17 2006/04/17 17:29:08 rpaulo Exp $ */
|
||||||
/* FreeBSD: src/sys/dev/ipw/if_ipw.c,v 1.15 2005/11/13 17:17:40 damien Exp */
|
/* FreeBSD: src/sys/dev/ipw/if_ipw.c,v 1.15 2005/11/13 17:17:40 damien Exp */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: if_ipw.c,v 1.16 2005/12/24 20:27:42 perry Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: if_ipw.c,v 1.17 2006/04/17 17:29:08 rpaulo Exp $");
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Intel(R) PRO/Wireless 2100 MiniPCI driver
|
* Intel(R) PRO/Wireless 2100 MiniPCI driver
|
||||||
|
@ -74,6 +74,8 @@ __KERNEL_RCSID(0, "$NetBSD: if_ipw.c,v 1.16 2005/12/24 20:27:42 perry Exp $");
|
||||||
#include <netinet/in_var.h>
|
#include <netinet/in_var.h>
|
||||||
#include <netinet/ip.h>
|
#include <netinet/ip.h>
|
||||||
|
|
||||||
|
#include <dev/firmload.h>
|
||||||
|
|
||||||
#include <dev/pci/if_ipwreg.h>
|
#include <dev/pci/if_ipwreg.h>
|
||||||
#include <dev/pci/if_ipwvar.h>
|
#include <dev/pci/if_ipwvar.h>
|
||||||
|
|
||||||
|
@ -121,7 +123,7 @@ static void ipw_stop_master(struct ipw_softc *);
|
||||||
static int ipw_reset(struct ipw_softc *);
|
static int ipw_reset(struct ipw_softc *);
|
||||||
static int ipw_load_ucode(struct ipw_softc *, u_char *, int);
|
static int ipw_load_ucode(struct ipw_softc *, u_char *, int);
|
||||||
static int ipw_load_firmware(struct ipw_softc *, u_char *, int);
|
static int ipw_load_firmware(struct ipw_softc *, u_char *, int);
|
||||||
static int ipw_cache_firmware(struct ipw_softc *, void *);
|
static int ipw_cache_firmware(struct ipw_softc *);
|
||||||
static void ipw_free_firmware(struct ipw_softc *);
|
static void ipw_free_firmware(struct ipw_softc *);
|
||||||
static int ipw_config(struct ipw_softc *);
|
static int ipw_config(struct ipw_softc *);
|
||||||
static int ipw_init(struct ifnet *);
|
static int ipw_init(struct ifnet *);
|
||||||
|
@ -218,6 +220,7 @@ ipw_attach(struct device *parent, struct device *self, void *aux)
|
||||||
sc->sc_st = memt;
|
sc->sc_st = memt;
|
||||||
sc->sc_sh = memh;
|
sc->sc_sh = memh;
|
||||||
sc->sc_dmat = pa->pa_dmat;
|
sc->sc_dmat = pa->pa_dmat;
|
||||||
|
strncpy(sc->sc_fwname, "ipw2100-1.2.fw", 16);
|
||||||
|
|
||||||
/* disable interrupts */
|
/* disable interrupts */
|
||||||
CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, 0);
|
CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, 0);
|
||||||
|
@ -1737,14 +1740,6 @@ ipw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||||
error = ipw_get_radio(sc, (int *)ifr->ifr_data);
|
error = ipw_get_radio(sc, (int *)ifr->ifr_data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SIOCSLOADFW:
|
|
||||||
/* only super-user can do that! */
|
|
||||||
if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) != 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
error = ipw_cache_firmware(sc, ifr->ifr_data);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SIOCSKILLFW:
|
case SIOCSKILLFW:
|
||||||
/* only super-user can do that! */
|
/* only super-user can do that! */
|
||||||
if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) != 0)
|
if ((error = suser(curproc->p_ucred, &curproc->p_acflag)) != 0)
|
||||||
|
@ -1753,6 +1748,16 @@ ipw_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||||
ipw_reset(sc);
|
ipw_reset(sc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SIOCSIFMEDIA:
|
||||||
|
if (ifr->ifr_media & IFM_IEEE80211_ADHOC)
|
||||||
|
strncpy(sc->sc_fwname, "ipw2100-1.2-i.fw", 16);
|
||||||
|
else if (ifr->ifr_media & IFM_IEEE80211_MONITOR)
|
||||||
|
strncpy(sc->sc_fwname, "ipw2100-1.2-p.fw", 16);
|
||||||
|
else
|
||||||
|
strncpy(sc->sc_fwname, "ipw2100-1.2.fw", 16);
|
||||||
|
|
||||||
|
ipw_free_firmware(sc);
|
||||||
|
/* FALLTRHOUGH */
|
||||||
default:
|
default:
|
||||||
error = ieee80211_ioctl(&sc->sc_ic, cmd, data);
|
error = ieee80211_ioctl(&sc->sc_ic, cmd, data);
|
||||||
if (error != ENETRESET)
|
if (error != ENETRESET)
|
||||||
|
@ -1968,39 +1973,51 @@ ipw_load_firmware(struct ipw_softc *sc, u_char *fw, int size)
|
||||||
* e.g when the adapter wakes up from suspend mode.
|
* e.g when the adapter wakes up from suspend mode.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
ipw_cache_firmware(struct ipw_softc *sc, void *data)
|
ipw_cache_firmware(struct ipw_softc *sc)
|
||||||
{
|
{
|
||||||
struct ipw_firmware *fw = &sc->fw;
|
struct ipw_firmware *fw = &sc->fw;
|
||||||
struct ipw_firmware_hdr hdr;
|
struct ipw_firmware_hdr hdr;
|
||||||
u_char *p = data;
|
firmware_handle_t fwh;
|
||||||
|
off_t fwsz, p;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
ipw_free_firmware(sc);
|
ipw_free_firmware(sc);
|
||||||
|
|
||||||
if ((error = copyin(data, &hdr, sizeof hdr)) != 0)
|
if ((error = firmware_open("if_ipw", sc->sc_fwname, &fwh)) != 0)
|
||||||
goto fail1;
|
goto fail0;
|
||||||
|
|
||||||
|
fwsz = firmware_get_size(fwh);
|
||||||
|
|
||||||
|
if (fwsz < sizeof(hdr))
|
||||||
|
goto fail2;
|
||||||
|
|
||||||
|
if ((error = firmware_read(fwh, 0, &hdr, sizeof(hdr))) != 0)
|
||||||
|
goto fail2;
|
||||||
|
|
||||||
fw->main_size = le32toh(hdr.main_size);
|
fw->main_size = le32toh(hdr.main_size);
|
||||||
fw->ucode_size = le32toh(hdr.ucode_size);
|
fw->ucode_size = le32toh(hdr.ucode_size);
|
||||||
p += sizeof hdr;
|
|
||||||
|
|
||||||
fw->main = malloc(fw->main_size, M_DEVBUF, M_NOWAIT);
|
fw->main = firmware_malloc(fw->main_size);
|
||||||
if (fw->main == NULL) {
|
if (fw->main == NULL) {
|
||||||
error = ENOMEM;
|
error = ENOMEM;
|
||||||
goto fail1;
|
goto fail1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fw->ucode = malloc(fw->ucode_size, M_DEVBUF, M_NOWAIT);
|
fw->ucode = firmware_malloc(fw->ucode_size);
|
||||||
if (fw->ucode == NULL) {
|
if (fw->ucode == NULL) {
|
||||||
error = ENOMEM;
|
error = ENOMEM;
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = copyin(p, fw->main, fw->main_size)) != 0)
|
p = sizeof(hdr);
|
||||||
|
if ((error = firmware_read(fwh, p, fw->main, fw->main_size)) != 0)
|
||||||
|
goto fail3;
|
||||||
|
|
||||||
|
if ((error = firmware_read(fwh, p, fw->main, fw->main_size)) != 0)
|
||||||
goto fail3;
|
goto fail3;
|
||||||
|
|
||||||
p += fw->main_size;
|
p += fw->main_size;
|
||||||
if ((error = copyin(p, fw->ucode, fw->ucode_size)) != 0)
|
if ((error = firmware_read(fwh, p, fw->ucode, fw->ucode_size)) != 0)
|
||||||
goto fail3;
|
goto fail3;
|
||||||
|
|
||||||
DPRINTF(("Firmware cached: main %u, ucode %u\n", fw->main_size,
|
DPRINTF(("Firmware cached: main %u, ucode %u\n", fw->main_size,
|
||||||
|
@ -2010,9 +2027,10 @@ ipw_cache_firmware(struct ipw_softc *sc, void *data)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail3: free(fw->ucode, M_DEVBUF);
|
fail3: firmware_free(fw->ucode, 0);
|
||||||
fail2: free(fw->main, M_DEVBUF);
|
fail2: firmware_free(fw->main, 0);
|
||||||
fail1:
|
fail1: firmware_close(fwh);
|
||||||
|
fail0:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2022,8 +2040,8 @@ ipw_free_firmware(struct ipw_softc *sc)
|
||||||
if (!(sc->flags & IPW_FLAG_FW_CACHED))
|
if (!(sc->flags & IPW_FLAG_FW_CACHED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
free(sc->fw.main, M_DEVBUF);
|
firmware_free(sc->fw.main, 0);
|
||||||
free(sc->fw.ucode, M_DEVBUF);
|
firmware_free(sc->fw.ucode, 0);
|
||||||
|
|
||||||
sc->flags &= ~IPW_FLAG_FW_CACHED;
|
sc->flags &= ~IPW_FLAG_FW_CACHED;
|
||||||
}
|
}
|
||||||
|
@ -2242,14 +2260,12 @@ ipw_init(struct ifnet *ifp)
|
||||||
struct ipw_softc *sc = ifp->if_softc;
|
struct ipw_softc *sc = ifp->if_softc;
|
||||||
struct ipw_firmware *fw = &sc->fw;
|
struct ipw_firmware *fw = &sc->fw;
|
||||||
|
|
||||||
/* exit immediately if firmware has not been ioctl'd */
|
|
||||||
if (!(sc->flags & IPW_FLAG_FW_CACHED)) {
|
if (!(sc->flags & IPW_FLAG_FW_CACHED)) {
|
||||||
if (!(sc->flags & IPW_FLAG_FW_WARNED))
|
if (ipw_cache_firmware(sc) != 0) {
|
||||||
aprint_error("%s: Please load firmware\n",
|
aprint_error("%s: could not cache the firmware (%s)\n",
|
||||||
sc->sc_dev.dv_xname);
|
sc->sc_dev.dv_xname, sc->sc_fwname);
|
||||||
sc->flags |= IPW_FLAG_FW_WARNED;
|
goto fail;
|
||||||
ifp->if_flags &= ~IFF_UP;
|
}
|
||||||
return EIO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ipw_stop(ifp, 0);
|
ipw_stop(ifp, 0);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $NetBSD: if_ipwvar.h,v 1.8 2005/12/20 07:51:38 skrll Exp $ */
|
/* $NetBSD: if_ipwvar.h,v 1.9 2006/04/17 17:29:08 rpaulo Exp $ */
|
||||||
|
|
||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2004
|
* Copyright (c) 2004
|
||||||
|
@ -93,6 +93,7 @@ struct ipw_softc {
|
||||||
enum ieee80211_state, int);
|
enum ieee80211_state, int);
|
||||||
|
|
||||||
struct ipw_firmware fw;
|
struct ipw_firmware fw;
|
||||||
|
char sc_fwname[16];
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
#define IPW_FLAG_FW_CACHED (1 << 0)
|
#define IPW_FLAG_FW_CACHED (1 << 0)
|
||||||
#define IPW_FLAG_FW_INITED (1 << 1)
|
#define IPW_FLAG_FW_INITED (1 << 1)
|
||||||
|
|
Loading…
Reference in New Issue