diff options
| -rw-r--r-- | drivers/char/pcmcia/ipwireless/hardware.c | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/drivers/char/pcmcia/ipwireless/hardware.c b/drivers/char/pcmcia/ipwireless/hardware.c index 7428734d08a1..08423ba5b9dd 100644 --- a/drivers/char/pcmcia/ipwireless/hardware.c +++ b/drivers/char/pcmcia/ipwireless/hardware.c | |||
| @@ -132,29 +132,17 @@ enum { | |||
| 132 | #define NL_FOLLOWING_PACKET_HEADER_SIZE 1 | 132 | #define NL_FOLLOWING_PACKET_HEADER_SIZE 1 |
| 133 | 133 | ||
| 134 | struct nl_first_packet_header { | 134 | struct nl_first_packet_header { |
| 135 | #if defined(__BIG_ENDIAN_BITFIELD) | ||
| 136 | unsigned char packet_rank:2; | ||
| 137 | unsigned char address:3; | ||
| 138 | unsigned char protocol:3; | ||
| 139 | #else | ||
| 140 | unsigned char protocol:3; | 135 | unsigned char protocol:3; |
| 141 | unsigned char address:3; | 136 | unsigned char address:3; |
| 142 | unsigned char packet_rank:2; | 137 | unsigned char packet_rank:2; |
| 143 | #endif | ||
| 144 | unsigned char length_lsb; | 138 | unsigned char length_lsb; |
| 145 | unsigned char length_msb; | 139 | unsigned char length_msb; |
| 146 | }; | 140 | }; |
| 147 | 141 | ||
| 148 | struct nl_packet_header { | 142 | struct nl_packet_header { |
| 149 | #if defined(__BIG_ENDIAN_BITFIELD) | ||
| 150 | unsigned char packet_rank:2; | ||
| 151 | unsigned char address:3; | ||
| 152 | unsigned char protocol:3; | ||
| 153 | #else | ||
| 154 | unsigned char protocol:3; | 143 | unsigned char protocol:3; |
| 155 | unsigned char address:3; | 144 | unsigned char address:3; |
| 156 | unsigned char packet_rank:2; | 145 | unsigned char packet_rank:2; |
| 157 | #endif | ||
| 158 | }; | 146 | }; |
| 159 | 147 | ||
| 160 | /* Value of 'packet_rank' above */ | 148 | /* Value of 'packet_rank' above */ |
| @@ -382,7 +370,37 @@ static void dump_data_bytes(const char *type, const unsigned char *data, | |||
| 382 | length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES); | 370 | length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES); |
| 383 | } | 371 | } |
| 384 | 372 | ||
| 385 | static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, | 373 | static void swap_packet_bitfield_to_le(unsigned char *data) |
| 374 | { | ||
| 375 | #ifdef __BIG_ENDIAN_BITFIELD | ||
| 376 | unsigned char tmp = *data, ret = 0; | ||
| 377 | |||
| 378 | /* | ||
| 379 | * transform bits from aa.bbb.ccc to ccc.bbb.aa | ||
| 380 | */ | ||
| 381 | ret |= tmp & 0xc0 >> 6; | ||
| 382 | ret |= tmp & 0x38 >> 1; | ||
| 383 | ret |= tmp & 0x07 << 5; | ||
| 384 | *data = ret & 0xff; | ||
| 385 | #endif | ||
| 386 | } | ||
| 387 | |||
| 388 | static void swap_packet_bitfield_from_le(unsigned char *data) | ||
| 389 | { | ||
| 390 | #ifdef __BIG_ENDIAN_BITFIELD | ||
| 391 | unsigned char tmp = *data, ret = 0; | ||
| 392 | |||
| 393 | /* | ||
| 394 | * transform bits from ccc.bbb.aa to aa.bbb.ccc | ||
| 395 | */ | ||
| 396 | ret |= tmp & 0xe0 >> 5; | ||
| 397 | ret |= tmp & 0x1c << 1; | ||
| 398 | ret |= tmp & 0x03 << 6; | ||
| 399 | *data = ret & 0xff; | ||
| 400 | #endif | ||
| 401 | } | ||
| 402 | |||
| 403 | static int do_send_fragment(struct ipw_hardware *hw, unsigned char *data, | ||
| 386 | unsigned length) | 404 | unsigned length) |
| 387 | { | 405 | { |
| 388 | unsigned i; | 406 | unsigned i; |
| @@ -402,6 +420,7 @@ static int do_send_fragment(struct ipw_hardware *hw, const unsigned char *data, | |||
| 402 | spin_lock_irqsave(&hw->lock, flags); | 420 | spin_lock_irqsave(&hw->lock, flags); |
| 403 | 421 | ||
| 404 | hw->tx_ready = 0; | 422 | hw->tx_ready = 0; |
| 423 | swap_packet_bitfield_to_le(data); | ||
| 405 | 424 | ||
| 406 | if (hw->hw_version == HW_VERSION_1) { | 425 | if (hw->hw_version == HW_VERSION_1) { |
| 407 | outw((unsigned short) length, hw->base_port + IODWR); | 426 | outw((unsigned short) length, hw->base_port + IODWR); |
| @@ -458,6 +477,10 @@ static int do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet) | |||
| 458 | if (data_left < fragment_data_len) | 477 | if (data_left < fragment_data_len) |
| 459 | fragment_data_len = data_left; | 478 | fragment_data_len = data_left; |
| 460 | 479 | ||
| 480 | /* | ||
| 481 | * hdr_first is now in machine bitfield order, which will be swapped | ||
| 482 | * to le just before it goes to hw | ||
| 483 | */ | ||
| 461 | pkt.hdr_first.protocol = packet->protocol; | 484 | pkt.hdr_first.protocol = packet->protocol; |
| 462 | pkt.hdr_first.address = packet->dest_addr; | 485 | pkt.hdr_first.address = packet->dest_addr; |
| 463 | pkt.hdr_first.packet_rank = 0; | 486 | pkt.hdr_first.packet_rank = 0; |
| @@ -883,6 +906,8 @@ static void do_receive_packet(struct ipw_hardware *hw) | |||
| 883 | 906 | ||
| 884 | acknowledge_data_read(hw); | 907 | acknowledge_data_read(hw); |
| 885 | 908 | ||
| 909 | swap_packet_bitfield_from_le(pkt); | ||
| 910 | |||
| 886 | if (ipwireless_debug) | 911 | if (ipwireless_debug) |
| 887 | dump_data_bytes("recv", pkt, len); | 912 | dump_data_bytes("recv", pkt, len); |
| 888 | 913 | ||
