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 */
|
||||
|
||||
/*-
|
||||
|
@ -29,7 +29,7 @@
|
|||
*/
|
||||
|
||||
#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
|
||||
|
@ -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/ip.h>
|
||||
|
||||
#include <dev/firmload.h>
|
||||
|
||||
#include <dev/pci/if_ipwreg.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_load_ucode(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 int ipw_config(struct ipw_softc *);
|
||||
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_sh = memh;
|
||||
sc->sc_dmat = pa->pa_dmat;
|
||||
strncpy(sc->sc_fwname, "ipw2100-1.2.fw", 16);
|
||||
|
||||
/* disable interrupts */
|
||||
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);
|
||||
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:
|
||||
/* only super-user can do that! */
|
||||
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);
|
||||
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:
|
||||
error = ieee80211_ioctl(&sc->sc_ic, cmd, data);
|
||||
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.
|
||||
*/
|
||||
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_hdr hdr;
|
||||
u_char *p = data;
|
||||
firmware_handle_t fwh;
|
||||
off_t fwsz, p;
|
||||
int error;
|
||||
|
||||
ipw_free_firmware(sc);
|
||||
|
||||
if ((error = copyin(data, &hdr, sizeof hdr)) != 0)
|
||||
goto fail1;
|
||||
if ((error = firmware_open("if_ipw", sc->sc_fwname, &fwh)) != 0)
|
||||
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->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) {
|
||||
error = ENOMEM;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
fw->ucode = malloc(fw->ucode_size, M_DEVBUF, M_NOWAIT);
|
||||
fw->ucode = firmware_malloc(fw->ucode_size);
|
||||
if (fw->ucode == NULL) {
|
||||
error = ENOMEM;
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
fail3: free(fw->ucode, M_DEVBUF);
|
||||
fail2: free(fw->main, M_DEVBUF);
|
||||
fail1:
|
||||
fail3: firmware_free(fw->ucode, 0);
|
||||
fail2: firmware_free(fw->main, 0);
|
||||
fail1: firmware_close(fwh);
|
||||
fail0:
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -2022,8 +2040,8 @@ 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);
|
||||
firmware_free(sc->fw.main, 0);
|
||||
firmware_free(sc->fw.ucode, 0);
|
||||
|
||||
sc->flags &= ~IPW_FLAG_FW_CACHED;
|
||||
}
|
||||
|
@ -2242,14 +2260,12 @@ ipw_init(struct ifnet *ifp)
|
|||
struct ipw_softc *sc = ifp->if_softc;
|
||||
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_WARNED))
|
||||
aprint_error("%s: Please load firmware\n",
|
||||
sc->sc_dev.dv_xname);
|
||||
sc->flags |= IPW_FLAG_FW_WARNED;
|
||||
ifp->if_flags &= ~IFF_UP;
|
||||
return EIO;
|
||||
if (ipw_cache_firmware(sc) != 0) {
|
||||
aprint_error("%s: could not cache the firmware (%s)\n",
|
||||
sc->sc_dev.dv_xname, sc->sc_fwname);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -93,6 +93,7 @@ struct ipw_softc {
|
|||
enum ieee80211_state, int);
|
||||
|
||||
struct ipw_firmware fw;
|
||||
char sc_fwname[16];
|
||||
uint32_t flags;
|
||||
#define IPW_FLAG_FW_CACHED (1 << 0)
|
||||
#define IPW_FLAG_FW_INITED (1 << 1)
|
||||
|
|
Loading…
Reference in New Issue