summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2000-12-15 23:34:13 +0000
committerwpaul <wpaul@FreeBSD.org>2000-12-15 23:34:13 +0000
commit82aa2600cc4e3cfc96e5448f398df3de50a2c4aa (patch)
tree2036d5faa338d01933e4732685adceb811b9fd8d /sys
parentea1bd4d5564b47e0114a1d3c8447ca78aa7121a1 (diff)
downloadFreeBSD-src-82aa2600cc4e3cfc96e5448f398df3de50a2c4aa.zip
FreeBSD-src-82aa2600cc4e3cfc96e5448f398df3de50a2c4aa.tar.gz
Apply some contributed patches to reduce number of tx buffer allocation
failures and add some support for WEP on Prism II chip. Submitted by: YAMAMOTO Shigeru <shigeru@iij.ad.jp>
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/wi/if_wi.c151
-rw-r--r--sys/dev/wi/if_wireg.h8
-rw-r--r--sys/i386/isa/if_wi.c151
-rw-r--r--sys/i386/isa/if_wireg.h8
4 files changed, 312 insertions, 6 deletions
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index c7c271c..0c99883 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -231,10 +231,34 @@ static int wi_pccard_attach(device_t dev)
struct wi_ltv_gen gen;
struct ifnet *ifp;
int error;
+ u_int32_t flags;
sc = device_get_softc(dev);
ifp = &sc->arpcom.ac_if;
+ /*
+ * XXX: quick hack to support Prism II chip.
+ * Currently, we need to set a flags in pccard.conf to specify
+ * which type chip is used.
+ *
+ * We need to replace this code in a future.
+ * It is better to use CIS than using a flag.
+ */
+ flags = device_get_flags(dev);
+#define WI_FLAGS_PRISM2 0x10000
+ if (flags & WI_FLAGS_PRISM2) {
+ sc->wi_prism2 = 1;
+ if (bootverbose) {
+ device_printf(dev, "found PrismII chip\n");
+ }
+ }
+ else {
+ sc->wi_prism2 = 0;
+ if (bootverbose) {
+ device_printf(dev, "found Lucent chip\n");
+ }
+ }
+
error = wi_alloc(dev);
if (error) {
device_printf(dev, "wi_alloc() failed! (%d)\n", error);
@@ -320,6 +344,12 @@ static int wi_pccard_attach(device_t dev)
wi_read_record(sc, &gen);
sc->wi_has_wep = gen.wi_val;
+ if (bootverbose) {
+ device_printf(sc->dev,
+ __FUNCTION__ ":wi_has_wep = %d\n",
+ sc->wi_has_wep);
+ }
+
bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
wi_init(sc);
@@ -589,7 +619,21 @@ static int wi_cmd(sc, cmd, val)
{
int i, s = 0;
+ /* wait for the busy bit to clear */
+ for (i = 0; i < WI_TIMEOUT; i++) {
+ if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) {
+ break;
+ }
+ DELAY(10*1000); /* 10 m sec */
+ }
+
+ if (i == WI_TIMEOUT) {
+ return(ETIMEDOUT);
+ }
+
CSR_WRITE_2(sc, WI_PARAM0, val);
+ CSR_WRITE_2(sc, WI_PARAM1, 0);
+ CSR_WRITE_2(sc, WI_PARAM2, 0);
CSR_WRITE_2(sc, WI_COMMAND, cmd);
for (i = 0; i < WI_TIMEOUT; i++) {
@@ -621,11 +665,12 @@ static int wi_cmd(sc, cmd, val)
static void wi_reset(sc)
struct wi_softc *sc;
{
+#ifdef foo
wi_cmd(sc, WI_CMD_INI, 0);
DELAY(100000);
wi_cmd(sc, WI_CMD_INI, 0);
+#endif
DELAY(100000);
-#ifdef foo
if (wi_cmd(sc, WI_CMD_INI, 0))
device_printf(sc->dev, "init failed\n");
CSR_WRITE_2(sc, WI_INT_EN, 0);
@@ -633,7 +678,7 @@ static void wi_reset(sc)
/* Calibrate timer. */
WI_SETVAL(WI_RID_TICK_TIME, 8);
-#endif
+
return;
}
@@ -646,6 +691,23 @@ static int wi_read_record(sc, ltv)
{
u_int16_t *ptr;
int i, len, code;
+ struct wi_ltv_gen *oltv, p2ltv;
+
+ oltv = ltv;
+ if (sc->wi_prism2) {
+ switch (ltv->wi_type) {
+ case WI_RID_ENCRYPTION:
+ p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
+ p2ltv.wi_len = 2;
+ ltv = &p2ltv;
+ break;
+ case WI_RID_TX_CRYPT_KEY:
+ p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
+ p2ltv.wi_len = 2;
+ ltv = &p2ltv;
+ break;
+ }
+ }
/* Tell the NIC to enter record read mode. */
if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
@@ -675,6 +737,35 @@ static int wi_read_record(sc, ltv)
for (i = 0; i < ltv->wi_len - 1; i++)
ptr[i] = CSR_READ_2(sc, WI_DATA1);
+ if (sc->wi_prism2) {
+ switch (oltv->wi_type) {
+ case WI_RID_TX_RATE:
+ case WI_RID_CUR_TX_RATE:
+ switch (ltv->wi_val) {
+ case 1: oltv->wi_val = 1; break;
+ case 2: oltv->wi_val = 2; break;
+ case 3: oltv->wi_val = 6; break;
+ case 4: oltv->wi_val = 5; break;
+ case 7: oltv->wi_val = 7; break;
+ case 8: oltv->wi_val = 11; break;
+ case 15: oltv->wi_val = 3; break;
+ default: oltv->wi_val = 0x100 + ltv->wi_val; break;
+ }
+ break;
+ case WI_RID_ENCRYPTION:
+ oltv->wi_len = 2;
+ if (ltv->wi_val & 0x01)
+ oltv->wi_val = 1;
+ else
+ oltv->wi_val = 0;
+ break;
+ case WI_RID_TX_CRYPT_KEY:
+ oltv->wi_len = 2;
+ oltv->wi_val = ltv->wi_val;
+ break;
+ }
+ }
+
return(0);
}
@@ -687,6 +778,59 @@ static int wi_write_record(sc, ltv)
{
u_int16_t *ptr;
int i;
+ struct wi_ltv_gen p2ltv;
+
+ if (sc->wi_prism2) {
+ switch (ltv->wi_type) {
+ case WI_RID_TX_RATE:
+ p2ltv.wi_type = WI_RID_TX_RATE;
+ p2ltv.wi_len = 2;
+ switch (ltv->wi_val) {
+ case 1: p2ltv.wi_val = 1; break;
+ case 2: p2ltv.wi_val = 2; break;
+ case 3: p2ltv.wi_val = 15; break;
+ case 5: p2ltv.wi_val = 4; break;
+ case 6: p2ltv.wi_val = 3; break;
+ case 7: p2ltv.wi_val = 7; break;
+ case 11: p2ltv.wi_val = 8; break;
+ default: return EINVAL;
+ }
+ ltv = &p2ltv;
+ break;
+ case WI_RID_ENCRYPTION:
+ p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
+ p2ltv.wi_len = 2;
+ if (ltv->wi_val)
+ p2ltv.wi_val = 0x03;
+ else
+ p2ltv.wi_val = 0x90;
+ ltv = &p2ltv;
+ break;
+ case WI_RID_TX_CRYPT_KEY:
+ p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
+ p2ltv.wi_len = 2;
+ p2ltv.wi_val = ltv->wi_val;
+ ltv = &p2ltv;
+ break;
+ case WI_RID_DEFLT_CRYPT_KEYS:
+ {
+ int error;
+ struct wi_ltv_str ws;
+ struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv;
+ for (i = 0; i < 4; i++) {
+ ws.wi_len = 4;
+ ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
+ memcpy(ws.wi_str, &wk->wi_keys[i].wi_keydat, 5);
+ ws.wi_str[5] = '\0';
+ error = wi_write_record(sc,
+ (struct wi_ltv_gen *)&ws);
+ if (error)
+ return error;
+ }
+ return 0;
+ }
+ }
+ }
if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
return(EIO);
@@ -1362,7 +1506,8 @@ static int wi_alloc(dev)
rid = 0;
sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
- 0, ~0, 1, RF_ACTIVE);
+ 0, ~0, (1 << 6),
+ rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
if (!sc->iobase) {
device_printf(dev, "No I/O space?!\n");
return (ENXIO);
diff --git a/sys/dev/wi/if_wireg.h b/sys/dev/wi/if_wireg.h
index f15e6c0..eb4ab7c 100644
--- a/sys/dev/wi/if_wireg.h
+++ b/sys/dev/wi/if_wireg.h
@@ -66,6 +66,13 @@ struct wi_counters {
#define WI_RID_DEFLT_CRYPT_KEYS 0xFCB0
#define WI_RID_TX_CRYPT_KEY 0xFCB1
#define WI_RID_WEP_AVAIL 0xFD4F
+#define WI_RID_P2_TX_CRYPT_KEY 0xFC23
+#define WI_RID_P2_CRYPT_KEY0 0xFC24
+#define WI_RID_P2_CRYPT_KEY1 0xFC25
+#define WI_RID_P2_CRYPT_KEY2 0xFC26
+#define WI_RID_P2_CRYPT_KEY3 0xFC27
+#define WI_RID_P2_ENCRYPTION 0xFC28
+#define WI_RID_CUR_TX_RATE 0xFD44 /* current TX rate */
struct wi_key {
u_int16_t wi_keylen;
u_int8_t wi_keydat[14];
@@ -118,6 +125,7 @@ struct wi_softc {
#endif
struct callout_handle wi_stat_ch;
struct mtx wi_mtx;
+ int wi_prism2; /* set to 1 if it uses a Prism II chip */
};
#define WI_LOCK(_sc) mtx_enter(&(_sc)->wi_mtx, MTX_DEF)
diff --git a/sys/i386/isa/if_wi.c b/sys/i386/isa/if_wi.c
index c7c271c..0c99883 100644
--- a/sys/i386/isa/if_wi.c
+++ b/sys/i386/isa/if_wi.c
@@ -231,10 +231,34 @@ static int wi_pccard_attach(device_t dev)
struct wi_ltv_gen gen;
struct ifnet *ifp;
int error;
+ u_int32_t flags;
sc = device_get_softc(dev);
ifp = &sc->arpcom.ac_if;
+ /*
+ * XXX: quick hack to support Prism II chip.
+ * Currently, we need to set a flags in pccard.conf to specify
+ * which type chip is used.
+ *
+ * We need to replace this code in a future.
+ * It is better to use CIS than using a flag.
+ */
+ flags = device_get_flags(dev);
+#define WI_FLAGS_PRISM2 0x10000
+ if (flags & WI_FLAGS_PRISM2) {
+ sc->wi_prism2 = 1;
+ if (bootverbose) {
+ device_printf(dev, "found PrismII chip\n");
+ }
+ }
+ else {
+ sc->wi_prism2 = 0;
+ if (bootverbose) {
+ device_printf(dev, "found Lucent chip\n");
+ }
+ }
+
error = wi_alloc(dev);
if (error) {
device_printf(dev, "wi_alloc() failed! (%d)\n", error);
@@ -320,6 +344,12 @@ static int wi_pccard_attach(device_t dev)
wi_read_record(sc, &gen);
sc->wi_has_wep = gen.wi_val;
+ if (bootverbose) {
+ device_printf(sc->dev,
+ __FUNCTION__ ":wi_has_wep = %d\n",
+ sc->wi_has_wep);
+ }
+
bzero((char *)&sc->wi_stats, sizeof(sc->wi_stats));
wi_init(sc);
@@ -589,7 +619,21 @@ static int wi_cmd(sc, cmd, val)
{
int i, s = 0;
+ /* wait for the busy bit to clear */
+ for (i = 0; i < WI_TIMEOUT; i++) {
+ if (!(CSR_READ_2(sc, WI_COMMAND) & WI_CMD_BUSY)) {
+ break;
+ }
+ DELAY(10*1000); /* 10 m sec */
+ }
+
+ if (i == WI_TIMEOUT) {
+ return(ETIMEDOUT);
+ }
+
CSR_WRITE_2(sc, WI_PARAM0, val);
+ CSR_WRITE_2(sc, WI_PARAM1, 0);
+ CSR_WRITE_2(sc, WI_PARAM2, 0);
CSR_WRITE_2(sc, WI_COMMAND, cmd);
for (i = 0; i < WI_TIMEOUT; i++) {
@@ -621,11 +665,12 @@ static int wi_cmd(sc, cmd, val)
static void wi_reset(sc)
struct wi_softc *sc;
{
+#ifdef foo
wi_cmd(sc, WI_CMD_INI, 0);
DELAY(100000);
wi_cmd(sc, WI_CMD_INI, 0);
+#endif
DELAY(100000);
-#ifdef foo
if (wi_cmd(sc, WI_CMD_INI, 0))
device_printf(sc->dev, "init failed\n");
CSR_WRITE_2(sc, WI_INT_EN, 0);
@@ -633,7 +678,7 @@ static void wi_reset(sc)
/* Calibrate timer. */
WI_SETVAL(WI_RID_TICK_TIME, 8);
-#endif
+
return;
}
@@ -646,6 +691,23 @@ static int wi_read_record(sc, ltv)
{
u_int16_t *ptr;
int i, len, code;
+ struct wi_ltv_gen *oltv, p2ltv;
+
+ oltv = ltv;
+ if (sc->wi_prism2) {
+ switch (ltv->wi_type) {
+ case WI_RID_ENCRYPTION:
+ p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
+ p2ltv.wi_len = 2;
+ ltv = &p2ltv;
+ break;
+ case WI_RID_TX_CRYPT_KEY:
+ p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
+ p2ltv.wi_len = 2;
+ ltv = &p2ltv;
+ break;
+ }
+ }
/* Tell the NIC to enter record read mode. */
if (wi_cmd(sc, WI_CMD_ACCESS|WI_ACCESS_READ, ltv->wi_type))
@@ -675,6 +737,35 @@ static int wi_read_record(sc, ltv)
for (i = 0; i < ltv->wi_len - 1; i++)
ptr[i] = CSR_READ_2(sc, WI_DATA1);
+ if (sc->wi_prism2) {
+ switch (oltv->wi_type) {
+ case WI_RID_TX_RATE:
+ case WI_RID_CUR_TX_RATE:
+ switch (ltv->wi_val) {
+ case 1: oltv->wi_val = 1; break;
+ case 2: oltv->wi_val = 2; break;
+ case 3: oltv->wi_val = 6; break;
+ case 4: oltv->wi_val = 5; break;
+ case 7: oltv->wi_val = 7; break;
+ case 8: oltv->wi_val = 11; break;
+ case 15: oltv->wi_val = 3; break;
+ default: oltv->wi_val = 0x100 + ltv->wi_val; break;
+ }
+ break;
+ case WI_RID_ENCRYPTION:
+ oltv->wi_len = 2;
+ if (ltv->wi_val & 0x01)
+ oltv->wi_val = 1;
+ else
+ oltv->wi_val = 0;
+ break;
+ case WI_RID_TX_CRYPT_KEY:
+ oltv->wi_len = 2;
+ oltv->wi_val = ltv->wi_val;
+ break;
+ }
+ }
+
return(0);
}
@@ -687,6 +778,59 @@ static int wi_write_record(sc, ltv)
{
u_int16_t *ptr;
int i;
+ struct wi_ltv_gen p2ltv;
+
+ if (sc->wi_prism2) {
+ switch (ltv->wi_type) {
+ case WI_RID_TX_RATE:
+ p2ltv.wi_type = WI_RID_TX_RATE;
+ p2ltv.wi_len = 2;
+ switch (ltv->wi_val) {
+ case 1: p2ltv.wi_val = 1; break;
+ case 2: p2ltv.wi_val = 2; break;
+ case 3: p2ltv.wi_val = 15; break;
+ case 5: p2ltv.wi_val = 4; break;
+ case 6: p2ltv.wi_val = 3; break;
+ case 7: p2ltv.wi_val = 7; break;
+ case 11: p2ltv.wi_val = 8; break;
+ default: return EINVAL;
+ }
+ ltv = &p2ltv;
+ break;
+ case WI_RID_ENCRYPTION:
+ p2ltv.wi_type = WI_RID_P2_ENCRYPTION;
+ p2ltv.wi_len = 2;
+ if (ltv->wi_val)
+ p2ltv.wi_val = 0x03;
+ else
+ p2ltv.wi_val = 0x90;
+ ltv = &p2ltv;
+ break;
+ case WI_RID_TX_CRYPT_KEY:
+ p2ltv.wi_type = WI_RID_P2_TX_CRYPT_KEY;
+ p2ltv.wi_len = 2;
+ p2ltv.wi_val = ltv->wi_val;
+ ltv = &p2ltv;
+ break;
+ case WI_RID_DEFLT_CRYPT_KEYS:
+ {
+ int error;
+ struct wi_ltv_str ws;
+ struct wi_ltv_keys *wk = (struct wi_ltv_keys *)ltv;
+ for (i = 0; i < 4; i++) {
+ ws.wi_len = 4;
+ ws.wi_type = WI_RID_P2_CRYPT_KEY0 + i;
+ memcpy(ws.wi_str, &wk->wi_keys[i].wi_keydat, 5);
+ ws.wi_str[5] = '\0';
+ error = wi_write_record(sc,
+ (struct wi_ltv_gen *)&ws);
+ if (error)
+ return error;
+ }
+ return 0;
+ }
+ }
+ }
if (wi_seek(sc, ltv->wi_type, 0, WI_BAP1))
return(EIO);
@@ -1362,7 +1506,8 @@ static int wi_alloc(dev)
rid = 0;
sc->iobase = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
- 0, ~0, 1, RF_ACTIVE);
+ 0, ~0, (1 << 6),
+ rman_make_alignment_flags(1 << 6) | RF_ACTIVE);
if (!sc->iobase) {
device_printf(dev, "No I/O space?!\n");
return (ENXIO);
diff --git a/sys/i386/isa/if_wireg.h b/sys/i386/isa/if_wireg.h
index f15e6c0..eb4ab7c 100644
--- a/sys/i386/isa/if_wireg.h
+++ b/sys/i386/isa/if_wireg.h
@@ -66,6 +66,13 @@ struct wi_counters {
#define WI_RID_DEFLT_CRYPT_KEYS 0xFCB0
#define WI_RID_TX_CRYPT_KEY 0xFCB1
#define WI_RID_WEP_AVAIL 0xFD4F
+#define WI_RID_P2_TX_CRYPT_KEY 0xFC23
+#define WI_RID_P2_CRYPT_KEY0 0xFC24
+#define WI_RID_P2_CRYPT_KEY1 0xFC25
+#define WI_RID_P2_CRYPT_KEY2 0xFC26
+#define WI_RID_P2_CRYPT_KEY3 0xFC27
+#define WI_RID_P2_ENCRYPTION 0xFC28
+#define WI_RID_CUR_TX_RATE 0xFD44 /* current TX rate */
struct wi_key {
u_int16_t wi_keylen;
u_int8_t wi_keydat[14];
@@ -118,6 +125,7 @@ struct wi_softc {
#endif
struct callout_handle wi_stat_ch;
struct mtx wi_mtx;
+ int wi_prism2; /* set to 1 if it uses a Prism II chip */
};
#define WI_LOCK(_sc) mtx_enter(&(_sc)->wi_mtx, MTX_DEF)
OpenPOWER on IntegriCloud