Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 28832
b: refs/heads/master
c: 725ad80
h: refs/heads/master
v: v3
  • Loading branch information
Gary Zambrano authored and Jeff Garzik committed Jun 23, 2006
1 parent d747d9c commit 0887605
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 00e8b3aa1cfd7577fd4019a24f7c3980506f83f3
refs/heads/master: 725ad800b73a71fe91bfd8859f928852de688ea0
110 changes: 109 additions & 1 deletion trunk/drivers/net/b44.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@
/* minimum number of free TX descriptors required to wake up TX process */
#define B44_TX_WAKEUP_THRESH (B44_TX_RING_SIZE / 4)

/* b44 internal pattern match filter info */
#define B44_PATTERN_BASE 0x400
#define B44_PATTERN_SIZE 0x80
#define B44_PMASK_BASE 0x600
#define B44_PMASK_SIZE 0x10
#define B44_MAX_PATTERNS 16
#define B44_ETHIPV6UDP_HLEN 62
#define B44_ETHIPV4UDP_HLEN 42

static char version[] __devinitdata =
DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";

Expand Down Expand Up @@ -1457,6 +1466,103 @@ static void b44_poll_controller(struct net_device *dev)
}
#endif

static void bwfilter_table(struct b44 *bp, u8 *pp, u32 bytes, u32 table_offset)
{
u32 i;
u32 *pattern = (u32 *) pp;

for (i = 0; i < bytes; i += sizeof(u32)) {
bw32(bp, B44_FILT_ADDR, table_offset + i);
bw32(bp, B44_FILT_DATA, pattern[i / sizeof(u32)]);
}
}

static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
{
int magicsync = 6;
int k, j, len = offset;
int ethaddr_bytes = ETH_ALEN;

memset(ppattern + offset, 0xff, magicsync);
for (j = 0; j < magicsync; j++)
set_bit(len++, (unsigned long *) pmask);

for (j = 0; j < B44_MAX_PATTERNS; j++) {
if ((B44_PATTERN_SIZE - len) >= ETH_ALEN)
ethaddr_bytes = ETH_ALEN;
else
ethaddr_bytes = B44_PATTERN_SIZE - len;
if (ethaddr_bytes <=0)
break;
for (k = 0; k< ethaddr_bytes; k++) {
ppattern[offset + magicsync +
(j * ETH_ALEN) + k] = macaddr[k];
len++;
set_bit(len, (unsigned long *) pmask);
}
}
return len - 1;
}

/* Setup magic packet patterns in the b44 WOL
* pattern matching filter.
*/
static void b44_setup_pseudo_magicp(struct b44 *bp)
{

u32 val;
int plen0, plen1, plen2;
u8 *pwol_pattern;
u8 pwol_mask[B44_PMASK_SIZE];

pwol_pattern = kmalloc(B44_PATTERN_SIZE, GFP_KERNEL);
if (!pwol_pattern) {
printk(KERN_ERR PFX "Memory not available for WOL\n");
return;
}

/* Ipv4 magic packet pattern - pattern 0.*/
memset(pwol_pattern, 0, B44_PATTERN_SIZE);
memset(pwol_mask, 0, B44_PMASK_SIZE);
plen0 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask,
B44_ETHIPV4UDP_HLEN);

bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE, B44_PATTERN_BASE);
bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE, B44_PMASK_BASE);

/* Raw ethernet II magic packet pattern - pattern 1 */
memset(pwol_pattern, 0, B44_PATTERN_SIZE);
memset(pwol_mask, 0, B44_PMASK_SIZE);
plen1 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask,
ETH_HLEN);

bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE,
B44_PATTERN_BASE + B44_PATTERN_SIZE);
bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE,
B44_PMASK_BASE + B44_PMASK_SIZE);

/* Ipv6 magic packet pattern - pattern 2 */
memset(pwol_pattern, 0, B44_PATTERN_SIZE);
memset(pwol_mask, 0, B44_PMASK_SIZE);
plen2 = b44_magic_pattern(bp->dev->dev_addr, pwol_pattern, pwol_mask,
B44_ETHIPV6UDP_HLEN);

bwfilter_table(bp, pwol_pattern, B44_PATTERN_SIZE,
B44_PATTERN_BASE + B44_PATTERN_SIZE + B44_PATTERN_SIZE);
bwfilter_table(bp, pwol_mask, B44_PMASK_SIZE,
B44_PMASK_BASE + B44_PMASK_SIZE + B44_PMASK_SIZE);

kfree(pwol_pattern);

/* set these pattern's lengths: one less than each real length */
val = plen0 | (plen1 << 8) | (plen2 << 16) | WKUP_LEN_ENABLE_THREE;
bw32(bp, B44_WKUP_LEN, val);

/* enable wakeup pattern matching */
val = br32(bp, B44_DEVCTRL);
bw32(bp, B44_DEVCTRL, val | DEVCTRL_PFE);

}

static void b44_setup_wol(struct b44 *bp)
{
Expand All @@ -1482,7 +1588,9 @@ static void b44_setup_wol(struct b44 *bp)
val = br32(bp, B44_DEVCTRL);
bw32(bp, B44_DEVCTRL, val | DEVCTRL_MPM | DEVCTRL_PFE);

}
} else {
b44_setup_pseudo_magicp(bp);
}

val = br32(bp, B44_SBTMSLOW);
bw32(bp, B44_SBTMSLOW, val | SBTMSLOW_PE);
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/net/b44.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
#define WKUP_LEN_P3_MASK 0x7f000000 /* Pattern 3 */
#define WKUP_LEN_P3_SHIFT 24
#define WKUP_LEN_D3 0x80000000
#define WKUP_LEN_DISABLE 0x80808080
#define WKUP_LEN_ENABLE_TWO 0x80800000
#define WKUP_LEN_ENABLE_THREE 0x80000000
#define B44_ISTAT 0x0020UL /* Interrupt Status */
#define ISTAT_LS 0x00000020 /* Link Change (B0 only) */
#define ISTAT_PME 0x00000040 /* Power Management Event */
Expand Down

0 comments on commit 0887605

Please sign in to comment.