aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Paul <wpaul@FreeBSD.org>2003-12-23 04:08:22 +0000
committerBill Paul <wpaul@FreeBSD.org>2003-12-23 04:08:22 +0000
commitee422a28d6f75d00cea42b32337df4b6e706c1ea (patch)
treebf9f1f3a9199c4028ebe0d1efac3fa602c1a337f
parentd1d7ef3e2393989d7c8615f9b455d1ad95cd49c6 (diff)
downloadsrc-ee422a28d6f75d00cea42b32337df4b6e706c1ea.tar.gz
src-ee422a28d6f75d00cea42b32337df4b6e706c1ea.zip
Re-do the handling of ndis_buffers. The NDIS_BUFFER structure is
supposed to be opaque to the driver, however it is exposed through several macros which expect certain behavior. In my original implementation, I used the mappedsystemva member of the structure to hold a pointer to the buffer and bytecount to hold the length. It turns out you must use the startva pointer to point to the page containing the start of the buffer and set byteoffset to the offset within the page where the buffer starts. So, for a buffer with address 'baseva,' startva is baseva & ~(PAGE_SIZE -1) and byteoffset is baseva & (PAGE_SIZE -1). We have to maintain this convention everywhere that ndis_buffers are used. Fortunately, Microsoft defines some macros for initializing and manipulating NDIS_BUFFER structures in ntddk.h. I adapted some of them for use here and used them where appropriate. This fixes the discrepancy I observed between how RX'ed packet sizes were being reported in the Broadcom wireless driver and the sample ethernet drivers that I've tested. This should also help the Intel Centrino wireless driver work. Also try to properly initialize the 802.11 BSS and IBSS channels. (Sadly, the channel value is meaningless since there's no way in the existing NDIS API to get/set the channel, but this should take care of any 'invalid channel (NULL)' messages printed on the console.
Notes
Notes: svn path=/head/; revision=123757
-rw-r--r--sys/compat/ndis/kern_ndis.c14
-rw-r--r--sys/compat/ndis/ntoskrnl_var.h14
-rw-r--r--sys/compat/ndis/subr_ndis.c24
-rw-r--r--sys/dev/if_ndis/if_ndis.c15
4 files changed, 45 insertions, 22 deletions
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c
index 29eb77429eda..1a41a54eef21 100644
--- a/sys/compat/ndis/kern_ndis.c
+++ b/sys/compat/ndis/kern_ndis.c
@@ -486,11 +486,8 @@ ndis_ptom(m0, p)
*m0 = NULL;
return(ENOBUFS);
}
- if (buf->nb_bytecount > buf->nb_size)
- m->m_len = buf->nb_size;
- else
- m->m_len = buf->nb_bytecount;
- m->m_data = buf->nb_mappedsystemva;
+ m->m_len = buf->nb_bytecount;
+ m->m_data = MDL_VA(buf);
MEXTADD(m, m->m_data, m->m_len, ndis_return_packet,
p->np_rsvd[0], 0, EXT_NDIS);
m->m_ext.ext_buf = (void *)p; /* XXX */
@@ -557,8 +554,7 @@ ndis_mtop(m0, p)
return(ENOMEM);
}
- buf->nb_bytecount = m->m_len;
- buf->nb_mappedsystemva = m->m_data;
+ MDL_INIT(buf, m->m_data, m->m_len);
if (priv->npp_head == NULL)
priv->npp_head = buf;
else
@@ -628,7 +624,7 @@ ndis_set_info(arg, oid, buf, buflen)
tv.tv_sec = 60;
tv.tv_usec = 0;
error = tsleep(&sc->ndis_block.nmb_wkupdpctimer,
- PPAUSE|PCATCH, "ndis", tvtohz(&tv));
+ PPAUSE|PCATCH, "ndisset", tvtohz(&tv));
rval = sc->ndis_block.nmb_setstat;
}
@@ -956,7 +952,7 @@ ndis_get_info(arg, oid, buf, buflen)
tv.tv_sec = 60;
tv.tv_usec = 0;
error = tsleep(&sc->ndis_block.nmb_wkupdpctimer,
- PPAUSE|PCATCH, "ndis", tvtohz(&tv));
+ PPAUSE|PCATCH, "ndisget", tvtohz(&tv));
rval = sc->ndis_block.nmb_getstat;
}
diff --git a/sys/compat/ndis/ntoskrnl_var.h b/sys/compat/ndis/ntoskrnl_var.h
index 9447d1b82a7c..5d87ff3e1caf 100644
--- a/sys/compat/ndis/ntoskrnl_var.h
+++ b/sys/compat/ndis/ntoskrnl_var.h
@@ -40,6 +40,20 @@
#define SPAN_PAGES(ptr, len) \
((uint32_t)((((uintptr_t)(ptr) & (PAGE_SIZE -1)) + \
(len) + (PAGE_SIZE - 1)) >> PAGE_SHIFT))
+#define PAGE_ALIGN(ptr) \
+ ((void *)((uintptr_t)(ptr) & ~(PAGE_SIZE - 1)))
+#define BYTE_OFFSET(ptr) \
+ ((uint32_t)((uintptr_t)(ptr) & (PAGE_SIZE - 1)))
+#define MDL_INIT(b, baseva, len) \
+ (b)->nb_next = NULL; \
+ (b)->nb_size = (uint16_t)(sizeof(struct ndis_buffer) + \
+ (sizeof(uint32_t) * SPAN_PAGES((baseva), (len)))); \
+ (b)->nb_flags = 0; \
+ (b)->nb_startva = (void *)PAGE_ALIGN((baseva)); \
+ (b)->nb_byteoffset = BYTE_OFFSET((baseva)); \
+ (b)->nb_bytecount = (uint32_t)(len);
+#define MDL_VA(b) \
+ ((void *)((char *)((b)->nb_startva) + (b)->nb_byteoffset))
typedef uint32_t kspin_lock;
diff --git a/sys/compat/ndis/subr_ndis.c b/sys/compat/ndis/subr_ndis.c
index e3c971d5917c..7e271a3cee65 100644
--- a/sys/compat/ndis/subr_ndis.c
+++ b/sys/compat/ndis/subr_ndis.c
@@ -822,7 +822,7 @@ ndis_vtophys_load(adapter, buf, mapreg, writedev, addrarray, arraysize)
nma.nma_fraglist = addrarray;
error = bus_dmamap_load(sc->ndis_mtag, map,
- buf->nb_mappedsystemva, buf->nb_bytecount, ndis_map_cb,
+ MDL_VA(buf), buf->nb_bytecount, ndis_map_cb,
(void *)&nma, BUS_DMA_NOWAIT);
if (error)
@@ -1612,9 +1612,7 @@ ndis_alloc_buf(status, buffer, pool, vaddr, len)
/* Save pointer to the pool. */
buf->nb_process = head;
- buf->nb_mappedsystemva = vaddr;
- buf->nb_size = len;
- buf->nb_next = NULL;
+ MDL_INIT(buf, vaddr, len);
*buffer = buf;
@@ -1654,7 +1652,7 @@ ndis_query_buf(buf, vaddr, len)
uint32_t *len;
{
if (vaddr != NULL)
- *vaddr = buf->nb_mappedsystemva;
+ *vaddr = MDL_VA(buf);
*len = buf->nb_bytecount;
return;
@@ -1670,7 +1668,7 @@ ndis_query_buf_safe(buf, vaddr, len, prio)
uint32_t prio;
{
if (vaddr != NULL)
- *vaddr = buf->nb_mappedsystemva;
+ *vaddr = MDL_VA(buf);
*len = buf->nb_bytecount;
return;
@@ -1876,9 +1874,11 @@ __stdcall static uint32_t
ndis_numpages(buf)
ndis_buffer *buf;
{
+ if (buf == NULL)
+ return(0);
if (buf->nb_bytecount == 0)
return(1);
- return(SPAN_PAGES(buf->nb_mappedsystemva, buf->nb_bytecount));
+ return(SPAN_PAGES(MDL_VA(buf), buf->nb_bytecount));
}
__stdcall static void
@@ -1886,6 +1886,9 @@ ndis_buf_physpages(buf, pages)
ndis_buffer *buf;
uint32_t *pages;
{
+ if (buf == NULL)
+ return;
+
*pages = ndis_numpages(buf);
return;
}
@@ -1896,7 +1899,10 @@ ndis_query_bufoffset(buf, off, len)
uint32_t *off;
uint32_t *len;
{
- *off = (uint32_t)buf->nb_mappedsystemva & (PAGE_SIZE - 1);
+ if (buf == NULL)
+ return;
+
+ *off = buf->nb_byteoffset;
*len = buf->nb_bytecount;
return;
@@ -2149,7 +2155,7 @@ ndis_firstbuf(packet, buf, firstva, firstlen, totlen)
*firstva = NULL;
*firstlen = *totlen = 0;
} else {
- *firstva = tmp->nb_mappedsystemva;
+ *firstva = MDL_VA(tmp);
*firstlen = *totlen = tmp->nb_bytecount;
for (tmp = tmp->nb_next; tmp != NULL; tmp = tmp->nb_next)
*totlen += tmp->nb_bytecount;
diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c
index 9752572f3c55..c6bd206da088 100644
--- a/sys/dev/if_ndis/if_ndis.c
+++ b/sys/dev/if_ndis/if_ndis.c
@@ -512,11 +512,17 @@ ndis_attach(dev)
}
#undef SETRATE
#undef INCRATE
+ /*
+ * The Microsoft API has no support for getting/setting
+ * channels, so we lie like a rug here. If you wan to
+ * select a channel, use the sysctl/registry interface.
+ */
for (i = 1; i < 11; i++) {
ic->ic_channels[i].ic_freq =
ieee80211_ieee2mhz(i, IEEE80211_CHAN_B);
ic->ic_channels[i].ic_flags = IEEE80211_CHAN_B;
}
+
i = sizeof(arg);
r = ndis_get_info(sc, OID_802_11_WEP_STATUS, &arg, &i);
if (arg != NDIS_80211_WEPSTAT_NOTSUPPORTED)
@@ -524,7 +530,8 @@ ndis_attach(dev)
ieee80211_node_attach(ifp);
ieee80211_media_init(ifp, ieee80211_media_change,
ieee80211_media_status);
- /*ic->ic_bss->ni_rates = ic->ic_sup_rates[IEEE80211_MODE_11G];*/
+ ic->ic_ibss_chan = &ic->ic_channels[1];
+ ic->ic_bss->ni_chan = &ic->ic_channels[1];
} else {
ifmedia_init(&sc->ifmedia, IFM_IMASK, ndis_ifmedia_upd,
ndis_ifmedia_sts);
@@ -568,7 +575,7 @@ static int
ndis_detach(dev)
device_t dev;
{
- struct ndis_softc *sc;
+ struct ndis_softc *sc;
struct ifnet *ifp;
sc = device_get_softc(dev);
@@ -747,7 +754,7 @@ static void
ndis_intr(arg)
void *arg;
{
- struct ndis_softc *sc;
+ struct ndis_softc *sc;
struct ifnet *ifp;
int is_our_intr = 0;
int call_isr = 0;
@@ -779,7 +786,7 @@ static void
ndis_tick(xsc)
void *xsc;
{
- struct ndis_softc *sc;
+ struct ndis_softc *sc;
__stdcall ndis_checkforhang_handler hangfunc;
uint8_t rval;
ndis_media_state linkstate;