/[orinoco]/orinoco/orinoco.c
ViewVC logotype

Diff of /orinoco/orinoco.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.12 by dgibson, Mon Oct 20 07:14:02 2003 UTC revision 1.13 by dgibson, Tue Oct 21 05:46:31 2003 UTC
# Line 416  Line 416 
416   *        port.  This is supposed to allow 802.1x to work sanely, but   *        port.  This is supposed to allow 802.1x to work sanely, but
417   *        doesn't seem to yet.   *        doesn't seem to yet.
418   *   *
419     * v0.14alpha2 -> ??? - ???? - David Gibson
420     *      o
421     *
422   * TODO   * TODO
423   *      o New wireless extensions API (patch from Moustafa   *      o New wireless extensions API (patch from Moustafa
424   *        Youssef, updated by Jim Carter and Pavel Roskin).   *        Youssef, updated by Jim Carter and Pavel Roskin).
# Line 532  MODULE_PARM(suppress_linkstatus, "i"); Line 535  MODULE_PARM(suppress_linkstatus, "i");
535    HERMES_MAX_MULTICAST : 0)*/    HERMES_MAX_MULTICAST : 0)*/
536  #define MAX_MULTICAST(priv)     (HERMES_MAX_MULTICAST)  #define MAX_MULTICAST(priv)     (HERMES_MAX_MULTICAST)
537    
538    #define ORINOCO_INTEN           (HERMES_EV_RX | HERMES_EV_ALLOC \
539                                     | HERMES_EV_TX | HERMES_EV_TXEXC \
540                                     | HERMES_EV_WTERR | HERMES_EV_INFO \
541                                     | HERMES_EV_INFDROP )
542    
543  /********************************************************************/  /********************************************************************/
544  /* Data tables                                                      */  /* Data tables                                                      */
545  /********************************************************************/  /********************************************************************/
# Line 563  struct { Line 571  struct {
571  #define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)  #define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table)
572    
573  /********************************************************************/  /********************************************************************/
574    /* Data types                                                       */
575    /********************************************************************/
576    
577    /********************************************************************/
578  /* Function prototypes                                              */  /* Function prototypes                                              */
579  /********************************************************************/  /********************************************************************/
580    
581    static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
582    
583    static int orinoco_debug_dump_recs(struct net_device *dev);
584    
585    static int __orinoco_program_rids(struct net_device *dev);
586    static void __orinoco_set_multicast_list(struct net_device *dev);
587    
588    /********************************************************************/
589    /* Internal helper functions                                        */
590    /********************************************************************/
591    
592    static inline void set_port_type(struct orinoco_private *priv)
593    {
594            switch (priv->iw_mode) {
595            case IW_MODE_INFRA:
596                    priv->port_type = 1;
597                    priv->createibss = 0;
598                    break;
599            case IW_MODE_ADHOC:
600                    if (priv->prefer_port3) {
601                            priv->port_type = 3;
602                            priv->createibss = 0;
603                    } else {
604                            priv->port_type = priv->ibss_port;
605                            priv->createibss = 1;
606                    }
607                    break;
608            default:
609                    printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
610                           priv->ndev->name);
611            }
612    }
613    
614    /********************************************************************/
615    /* Device methods                                                   */
616    /********************************************************************/
617    
618    static int orinoco_open(struct net_device *dev)
619    {
620            struct orinoco_private *priv = dev->priv;
621            unsigned long flags;
622            int err;
623    
624            err = orinoco_lock(priv, &flags);
625            if (err)
626                    return err;
627    
628            err = __orinoco_up(dev);
629    
630            if (! err)
631                    priv->open = 1;
632    
633            orinoco_unlock(priv, &flags);
634    
635            return err;
636    }
637    
638    int orinoco_stop(struct net_device *dev)
639    {
640            struct orinoco_private *priv = dev->priv;
641            int err = 0;
642    
643            /* We mustn't use orinoco_lock() here, because we need to be
644               able to close the interface even if hw_unavailable is set
645               (e.g. as we're released after a PC Card removal) */
646            orinoco_spin_lock(priv);
647    
648            priv->open = 0;
649    
650            err = __orinoco_down(dev);
651    
652            orinoco_spin_unlock(priv);
653    
654            return err;
655    }
656    
657    struct net_device_stats *orinoco_get_stats(struct net_device *dev)
658    {
659            struct orinoco_private *priv = dev->priv;
660            
661            return &priv->stats;
662    }
663    
664    struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
665    {
666            struct orinoco_private *priv = dev->priv;
667            hermes_t *hw = &priv->hw;
668            struct iw_statistics *wstats = &priv->wstats;
669            int err = 0;
670            unsigned long flags;
671    
672            if (! netif_device_present(dev)) {
673                    printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",
674                           dev->name);
675                    return NULL; /* FIXME: Can we do better than this? */
676            }
677    
678            err = orinoco_lock(priv, &flags);
679            if (err)
680                    return NULL; /* FIXME: Erg, we've been signalled, how
681                                  * do we propagate this back up? */
682    
683            if (priv->iw_mode == IW_MODE_ADHOC) {
684                    memset(&wstats->qual, 0, sizeof(wstats->qual));
685                    /* If a spy address is defined, we report stats of the
686                     * first spy address - Jean II */
687                    if (SPY_NUMBER(priv)) {
688                            wstats->qual.qual = priv->spy_stat[0].qual;
689                            wstats->qual.level = priv->spy_stat[0].level;
690                            wstats->qual.noise = priv->spy_stat[0].noise;
691                            wstats->qual.updated = priv->spy_stat[0].updated;
692                    }
693            } else {
694                    struct {
695                            u16 qual, signal, noise;
696                    } __attribute__ ((packed)) cq;
697    
698                    err = HERMES_READ_RECORD(hw, USER_BAP,
699                                             HERMES_RID_COMMSQUALITY, &cq);
700                    
701                    wstats->qual.qual = (int)le16_to_cpu(cq.qual);
702                    wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;
703                    wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;
704                    wstats->qual.updated = 7;
705            }
706    
707            /* We can't really wait for the tallies inquiry command to
708             * complete, so we just use the previous results and trigger
709             * a new tallies inquiry command for next time - Jean II */
710            /* FIXME: We're in user context (I think?), so we should just
711               wait for the tallies to come through */
712            err = hermes_inquire(hw, HERMES_INQ_TALLIES);
713                  
714            orinoco_unlock(priv, &flags);
715    
716            if (err)
717                    return NULL;
718                    
719            return wstats;
720    }
721    
722    static void orinoco_set_multicast_list(struct net_device *dev)
723    {
724            struct orinoco_private *priv = dev->priv;
725            unsigned long flags;
726    
727            if (orinoco_lock(priv, &flags) != 0) {
728                    printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
729                           "called when hw_unavailable\n", dev->name);
730                    return;
731            }
732    
733            __orinoco_set_multicast_list(dev);
734            orinoco_unlock(priv, &flags);
735    }
736    
737    static int orinoco_change_mtu(struct net_device *dev, int new_mtu)
738    {
739            struct orinoco_private *priv = dev->priv;
740    
741            if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )
742                    return -EINVAL;
743    
744            if ( (new_mtu + ENCAPS_OVERHEAD + IEEE802_11_HLEN) >
745                 (priv->nicbuf_size - ETH_HLEN) )
746                    return -EINVAL;
747    
748            dev->mtu = new_mtu;
749    
750            return 0;
751    }
752    
753    /********************************************************************/
754    /* Tx path                                                          */
755    /********************************************************************/
756    
757    static int orinoco_xmit(struct sk_buff *skb, struct net_device *dev)
758    {
759            struct orinoco_private *priv = (struct orinoco_private *)dev->priv;
760            struct net_device_stats *stats = &priv->stats;
761            hermes_t *hw = &priv->hw;
762            int err = 0;
763            u16 txfid = priv->txfid;
764            char *p;
765            struct ethhdr *eh;
766            int len, data_len, data_off;
767            struct hermes_tx_descriptor desc;
768            unsigned long flags;
769    
770            TRACE_ENTER(dev->name);
771    
772            if (! netif_running(dev)) {
773                    printk(KERN_ERR "%s: Tx on stopped device!\n",
774                           dev->name);
775                    TRACE_EXIT(dev->name);
776                    return 1;
777            }
778            
779            if (netif_queue_stopped(dev)) {
780                    printk(KERN_DEBUG "%s: Tx while transmitter busy!\n",
781                           dev->name);
782                    TRACE_EXIT(dev->name);
783                    return 1;
784            }
785            
786            if (orinoco_lock(priv, &flags) != 0) {
787                    printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",
788                           dev->name);
789                    TRACE_EXIT(dev->name);
790                    return 1;
791            }
792    
793            if (! netif_carrier_ok(dev)) {
794                    /* Oops, the firmware hasn't established a connection,
795                       silently drop the packet (this seems to be the
796                       safest approach). */
797                    stats->tx_errors++;
798                    orinoco_unlock(priv, &flags);
799                    dev_kfree_skb(skb);
800                    TRACE_EXIT(dev->name);
801                    return 0;
802            }
803    
804            /* Length of the packet body */
805            /* FIXME: what if the skb is smaller than this? */
806            len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN);
807    
808            eh = (struct ethhdr *)skb->data;
809    
810            memset(&desc, 0, sizeof(desc));
811            desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
812            err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
813            if (err) {
814                    printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n",
815                           dev->name, err);
816                    stats->tx_errors++;
817                    goto fail;
818            }
819    
820            /* Clear the 802.11 header and data length fields - some
821             * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused
822             * if this isn't done. */
823            hermes_clear_words(hw, HERMES_DATA0,
824                               HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);
825    
826            /* Encapsulate Ethernet-II frames */
827            if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */
828                    struct header_struct hdr;
829                    data_len = len;
830                    data_off = HERMES_802_3_OFFSET + sizeof(hdr);
831                    p = skb->data + ETH_HLEN;
832    
833                    /* 802.3 header */
834                    memcpy(hdr.dest, eh->h_dest, ETH_ALEN);
835                    memcpy(hdr.src, eh->h_source, ETH_ALEN);
836                    hdr.len = htons(data_len + ENCAPS_OVERHEAD);
837                    
838                    /* 802.2 header */
839                    memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr));
840                            
841                    hdr.ethertype = eh->h_proto;
842                    err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),
843                                             txfid, HERMES_802_3_OFFSET);
844                    if (err) {
845                            printk(KERN_ERR "%s: Error %d writing packet header to BAP\n",
846                                   dev->name, err);
847                            stats->tx_errors++;
848                            goto fail;
849                    }
850            } else { /* IEEE 802.3 frame */
851                    data_len = len + ETH_HLEN;
852                    data_off = HERMES_802_3_OFFSET;
853                    p = skb->data;
854            }
855    
856            /* Round up for odd length packets */
857            err = hermes_bap_pwrite(hw, USER_BAP, p, ALIGN(data_len, 2),
858                                    txfid, data_off);
859            if (err) {
860                    printk(KERN_ERR "%s: Error %d writing packet to BAP\n",
861                           dev->name, err);
862                    stats->tx_errors++;
863                    goto fail;
864            }
865    
866            /* Finally, we actually initiate the send */
867            netif_stop_queue(dev);
868    
869            err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,
870                                    txfid, NULL);
871            if (err) {
872                    netif_start_queue(dev);
873                    printk(KERN_ERR "%s: Error %d transmitting packet\n",
874                           dev->name, err);
875                    stats->tx_errors++;
876                    goto fail;
877            }
878    
879            dev->trans_start = jiffies;
880            stats->tx_bytes += data_off + data_len;
881    
882            orinoco_unlock(priv, &flags);
883    
884            dev_kfree_skb(skb);
885    
886            TRACE_EXIT(dev->name);
887    
888            return 0;
889     fail:
890            TRACE_EXIT(dev->name);
891    
892            orinoco_unlock(priv, &flags);
893            return err;
894    }
895    
896    static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)
897    {
898            struct orinoco_private *priv = dev->priv;
899            u16 fid = hermes_read_regn(hw, ALLOCFID);
900    
901            if (fid != priv->txfid) {
902                    if (fid != DUMMY_FID)
903                            printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
904                                   dev->name, fid);
905                    return;
906            }
907    
908            hermes_write_regn(hw, ALLOCFID, DUMMY_FID);
909    }
910    
911    static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)
912    {
913            struct orinoco_private *priv = dev->priv;
914            struct net_device_stats *stats = &priv->stats;
915    
916            stats->tx_packets++;
917    
918            netif_wake_queue(dev);
919    
920            hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
921    }
922    
923    static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)
924    {
925            struct orinoco_private *priv = dev->priv;
926            struct net_device_stats *stats = &priv->stats;
927            u16 fid = hermes_read_regn(hw, TXCOMPLFID);
928            struct hermes_tx_descriptor desc;
929            int err = 0;
930    
931            if (fid == DUMMY_FID)
932                    return; /* Nothing's really happened */
933    
934            err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0);
935            if (err) {
936                    printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
937                           "(FID=%04X error %d)\n",
938                           dev->name, fid, err);
939            } else {
940                    DEBUG(1, "%s: Tx error, status %d\n",
941                          dev->name, le16_to_cpu(desc.status));
942            }
943            
944            stats->tx_errors++;
945    
946            hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
947    }
948    
949    static void orinoco_tx_timeout(struct net_device *dev)
950    {
951            struct orinoco_private *priv = (struct orinoco_private *)dev->priv;
952            struct net_device_stats *stats = &priv->stats;
953            struct hermes *hw = &priv->hw;
954    
955            printk(KERN_WARNING "%s: Tx timeout! "
956                   "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",
957                   dev->name, hermes_read_regn(hw, ALLOCFID),
958                   hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));
959    
960            stats->tx_errors++;
961    
962            schedule_work(&priv->reset_work);
963    }
964    
965    /********************************************************************/
966    /* Rx path (data frames)                                            */
967    /********************************************************************/
968    
969    /* Does the frame have a SNAP header indicating it should be
970     * de-encapsulated to Ethernet-II? */
971    static inline int is_ethersnap(struct header_struct *hdr)
972    {
973            /* We de-encapsulate all packets which, a) have SNAP headers
974             * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header
975             * and where b) the OUI of the SNAP header is 00:00:00 or
976             * 00:00:f8 - we need both because different APs appear to use
977             * different OUIs for some reason */
978            return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0)
979                    && ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) );
980    }
981    
982    static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
983                                        int level, int noise)
984    {
985            struct orinoco_private *priv = (struct orinoco_private *)dev->priv;
986            int i;
987    
988            /* Gather wireless spy statistics: for each packet, compare the
989             * source address with out list, and if match, get the stats... */
990            for (i = 0; i < priv->spy_number; i++)
991                    if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {
992                            priv->spy_stat[i].level = level - 0x95;
993                            priv->spy_stat[i].noise = noise - 0x95;
994                            priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;
995                            priv->spy_stat[i].updated = 7;
996                    }
997    }
998    
999  static void orinoco_stat_gather(struct net_device *dev,  static void orinoco_stat_gather(struct net_device *dev,
1000                                  struct sk_buff *skb,                                  struct sk_buff *skb,
1001                                  struct hermes_rx_descriptor *desc);                                  struct hermes_rx_descriptor *desc)
1002    {
1003            struct orinoco_private *priv = (struct orinoco_private *)dev->priv;
1004    
1005  static struct net_device_stats *orinoco_get_stats(struct net_device *dev);          /* Using spy support with lots of Rx packets, like in an
1006  static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev);           * infrastructure (AP), will really slow down everything, because
1007             * the MAC address must be compared to each entry of the spy list.
1008             * If the user really asks for it (set some address in the
1009             * spy list), we do it, but he will pay the price.
1010             * Note that to get here, you need both WIRELESS_SPY
1011             * compiled in AND some addresses in the list !!!
1012             */
1013            /* Note : gcc will optimise the whole section away if
1014             * WIRELESS_SPY is not defined... - Jean II */
1015            if (SPY_NUMBER(priv)) {
1016                    orinoco_spy_gather(dev, skb->mac.raw + ETH_ALEN,
1017                                       desc->signal, desc->silence);
1018            }
1019    }
1020    
1021  /* Hardware control routines */  void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)
1022    {
1023            struct orinoco_private *priv = dev->priv;
1024            struct net_device_stats *stats = &priv->stats;
1025            struct iw_statistics *wstats = &priv->wstats;
1026            struct sk_buff *skb = NULL;
1027            u16 rxfid, status;
1028            int length, data_len, data_off;
1029            char *p;
1030            struct hermes_rx_descriptor desc;
1031            struct header_struct hdr;
1032            struct ethhdr *eh;
1033            int err;
1034    
1035  static int __orinoco_program_rids(struct net_device *dev);          rxfid = hermes_read_regn(hw, RXFID);
1036    
1037  static int __orinoco_hw_set_bitrate(struct orinoco_private *priv);          err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc),
1038  static int __orinoco_hw_setup_wep(struct orinoco_private *priv);                                 rxfid, 0);
1039  static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN]);          if (err) {
1040  static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,                  printk(KERN_ERR "%s: error %d reading Rx descriptor. "
1041                                  char buf[IW_ESSID_MAX_SIZE+1]);                         "Frame dropped.\n", dev->name, err);
1042  static long orinoco_hw_get_freq(struct orinoco_private *priv);                  stats->rx_errors++;
1043  static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates,                  goto drop;
1044                                        s32 *rates, int max);          }
 static void __orinoco_set_multicast_list(struct net_device *dev);  
1045    
1046  /* Interrupt handling routines */          status = le16_to_cpu(desc.status);
1047  static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw);          
1048  static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw);          if (status & HERMES_RXSTAT_ERR) {
1049  static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw);                  if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
1050  void __orinoco_ev_info(struct net_device *dev, hermes_t *hw);                          wstats->discard.code++;
1051  void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw);                          DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
1052  static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw);                                 dev->name);
1053  static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw);                  } else {
1054  static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw);                          stats->rx_crc_errors++;
1055                            DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);
1056                    }
1057                    stats->rx_errors++;
1058                    goto drop;
1059            }
1060    
1061  /* ioctl() routines */          /* For now we ignore the 802.11 header completely, assuming
1062  static int orinoco_debug_dump_recs(struct net_device *dev);             that the card's firmware has handled anything vital */
1063    
1064            err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr),
1065                                   rxfid, HERMES_802_3_OFFSET);
1066            if (err) {
1067                    printk(KERN_ERR "%s: error %d reading frame header. "
1068                           "Frame dropped.\n", dev->name, err);
1069                    stats->rx_errors++;
1070                    goto drop;
1071            }
1072    
1073            length = ntohs(hdr.len);
1074            
1075            /* Sanity checks */
1076            if (length < 3) { /* No for even an 802.2 LLC header */
1077                    /* At least on Symbol firmware with PCF we get quite a
1078                       lot of these legitimately - Poll frames with no
1079                       data. */
1080                    stats->rx_dropped++;
1081                    goto drop;
1082            }
1083            if (length > IEEE802_11_DATA_LEN) {
1084                    printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
1085                           dev->name, length);
1086                    stats->rx_length_errors++;
1087                    stats->rx_errors++;
1088                    goto drop;
1089            }
1090    
1091            /* We need space for the packet data itself, plus an ethernet
1092               header, plus 2 bytes so we can align the IP header on a
1093               32bit boundary, plus 1 byte so we can read in odd length
1094               packets from the card, which has an IO granularity of 16
1095               bits */  
1096            skb = dev_alloc_skb(length+ETH_HLEN+2+1);
1097            if (!skb) {
1098                    printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
1099                           dev->name);
1100                    goto drop;
1101            }
1102    
1103            skb_reserve(skb, 2); /* This way the IP header is aligned */
1104    
1105            /* Handle decapsulation
1106             * In most cases, the firmware tell us about SNAP frames.
1107             * For some reason, the SNAP frames sent by LinkSys APs
1108             * are not properly recognised by most firmwares.
1109             * So, check ourselves */
1110            if(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||
1111               ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||
1112               is_ethersnap(&hdr)) {
1113                    /* These indicate a SNAP within 802.2 LLC within
1114                       802.11 frame which we'll need to de-encapsulate to
1115                       the original EthernetII frame. */
1116    
1117                    if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */
1118                            stats->rx_length_errors++;
1119                            goto drop;
1120                    }
1121    
1122                    /* Remove SNAP header, reconstruct EthernetII frame */
1123                    data_len = length - ENCAPS_OVERHEAD;
1124                    data_off = HERMES_802_3_OFFSET + sizeof(hdr);
1125    
1126                    eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);
1127    
1128                    memcpy(eh, &hdr, 2 * ETH_ALEN);
1129                    eh->h_proto = hdr.ethertype;
1130            } else {
1131                    /* All other cases indicate a genuine 802.3 frame.  No
1132                       decapsulation needed.  We just throw the whole
1133                       thing in, and hope the protocol layer can deal with
1134                       it as 802.3 */
1135                    data_len = length;
1136                    data_off = HERMES_802_3_OFFSET;
1137                    /* FIXME: we re-read from the card data we already read here */
1138            }
1139    
1140            p = skb_put(skb, data_len);
1141            err = hermes_bap_pread(hw, IRQ_BAP, p, ALIGN(data_len, 2),
1142                                   rxfid, data_off);
1143            if (err) {
1144                    printk(KERN_ERR "%s: error %d reading frame. "
1145                           "Frame dropped.\n", dev->name, err);
1146                    stats->rx_errors++;
1147                    goto drop;
1148            }
1149    
1150            dev->last_rx = jiffies;
1151            skb->dev = dev;
1152            skb->protocol = eth_type_trans(skb, dev);
1153            skb->ip_summed = CHECKSUM_NONE;
1154            
1155            /* Process the wireless stats if needed */
1156            orinoco_stat_gather(dev, skb, &desc);
1157    
1158            /* Pass the packet to the networking stack */
1159            netif_rx(skb);
1160            stats->rx_packets++;
1161            stats->rx_bytes += length;
1162    
1163            return;
1164    
1165     drop:  
1166            stats->rx_dropped++;
1167    
1168            if (skb)
1169                    dev_kfree_skb_irq(skb);
1170            return;
1171    }
1172    
1173  /********************************************************************/  /********************************************************************/
1174  /* Function prototypes                                              */  /* Rx path (info frames)                                            */
1175    /********************************************************************/
1176    
1177    static void print_linkstatus(struct net_device *dev, u16 status)
1178    {
1179            char * s;
1180    
1181            if (suppress_linkstatus)
1182                    return;
1183    
1184            switch (status) {
1185            case HERMES_LINKSTATUS_NOT_CONNECTED:
1186                    s = "Not Connected";
1187                    break;
1188            case HERMES_LINKSTATUS_CONNECTED:
1189                    s = "Connected";
1190                    break;
1191            case HERMES_LINKSTATUS_DISCONNECTED:
1192                    s = "Disconnected";
1193                    break;
1194            case HERMES_LINKSTATUS_AP_CHANGE:
1195                    s = "AP Changed";
1196                    break;
1197            case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
1198                    s = "AP Out of Range";
1199                    break;
1200            case HERMES_LINKSTATUS_AP_IN_RANGE:
1201                    s = "AP In Range";
1202                    break;
1203            case HERMES_LINKSTATUS_ASSOC_FAILED:
1204                    s = "Association Failed";
1205                    break;
1206            default:
1207                    s = "UNKNOWN";
1208            }
1209            
1210            printk(KERN_INFO "%s: New link status: %s (%04x)\n",
1211                   dev->name, s, status);
1212    }
1213    
1214    void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)
1215    {
1216            struct orinoco_private *priv = dev->priv;
1217            u16 infofid;
1218            struct {
1219                    u16 len;
1220                    u16 type;
1221            } __attribute__ ((packed)) info;
1222            int len, type;
1223            int err;
1224    
1225            /* This is an answer to an INQUIRE command that we did earlier,
1226             * or an information "event" generated by the card
1227             * The controller return to us a pseudo frame containing
1228             * the information in question - Jean II */
1229            infofid = hermes_read_regn(hw, INFOFID);
1230    
1231            /* Read the info frame header - don't try too hard */
1232            err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),
1233                                   infofid, 0);
1234            if (err) {
1235                    printk(KERN_ERR "%s: error %d reading info frame. "
1236                           "Frame dropped.\n", dev->name, err);
1237                    return;
1238            }
1239            
1240            len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len));
1241            type = le16_to_cpu(info.type);
1242    
1243            switch (type) {
1244            case HERMES_INQ_TALLIES: {
1245                    struct hermes_tallies_frame tallies;
1246                    struct iw_statistics *wstats = &priv->wstats;
1247                    
1248                    if (len > sizeof(tallies)) {
1249                            printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n",
1250                                   dev->name, len);
1251                            len = sizeof(tallies);
1252                    }
1253                    
1254                    /* Read directly the data (no seek) */
1255                    /* FIXME: blech! ??? */
1256                    hermes_bap_pread(hw, IRQ_BAP, &tallies, len, infofid, sizeof(info));
1257    
1258                    /* Increment our various counters */
1259                    /* wstats->discard.nwid - no wrong BSSID stuff */
1260                    wstats->discard.code +=
1261                            le16_to_cpu(tallies.RxWEPUndecryptable);
1262                    if (len == sizeof(tallies))  
1263                            wstats->discard.code +=
1264                                    le16_to_cpu(tallies.RxDiscards_WEPICVError) +
1265                                    le16_to_cpu(tallies.RxDiscards_WEPExcluded);
1266                    wstats->discard.misc +=
1267                            le16_to_cpu(tallies.TxDiscardsWrongSA);
1268    #if WIRELESS_EXT > 11
1269                    wstats->discard.fragment +=
1270                            le16_to_cpu(tallies.RxMsgInBadMsgFragments);
1271                    wstats->discard.retries +=
1272                            le16_to_cpu(tallies.TxRetryLimitExceeded);
1273                    /* wstats->miss.beacon - no match */
1274    #endif /* WIRELESS_EXT > 11 */
1275            }
1276            break;
1277            case HERMES_INQ_LINKSTATUS: {
1278                    struct hermes_linkstatus linkstatus;
1279                    u16 newstatus;
1280                    
1281                    if (len != sizeof(linkstatus)) {
1282                            printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
1283                                   dev->name, len);
1284                            break;
1285                    }
1286    
1287                    hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len, infofid, sizeof(info));
1288    
1289                    newstatus = le16_to_cpu(linkstatus.linkstatus);
1290    
1291                    if ( (newstatus == HERMES_LINKSTATUS_CONNECTED)
1292                         || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)
1293                         || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE) )
1294                            netif_carrier_on(dev);
1295                    else if ( (newstatus == HERMES_LINKSTATUS_NOT_CONNECTED)
1296                              || (newstatus == HERMES_LINKSTATUS_DISCONNECTED)
1297                              || (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE)
1298                              || (newstatus == HERMES_LINKSTATUS_ASSOC_FAILED) )
1299                            netif_carrier_off(dev);
1300    
1301                    if (newstatus != priv->last_linkstatus)
1302                            print_linkstatus(dev, newstatus);
1303    
1304                    priv->last_linkstatus = newstatus;
1305            }
1306            break;
1307            default:
1308                    printk(KERN_DEBUG "%s: Unknown information frame received (type %04x).\n",
1309                          dev->name, type);
1310                    /* We don't actually do anything about it */
1311                    break;
1312            }
1313    }
1314    
1315    static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)
1316    {
1317            printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name);
1318    }
1319    
1320    /********************************************************************/
1321    /* Internal hardware control routines                               */
1322  /********************************************************************/  /********************************************************************/
1323    
1324  int __orinoco_up(struct net_device *dev)  int __orinoco_up(struct net_device *dev)
# Line 692  int orinoco_reinit_firmware(struct net_d Line 1409  int orinoco_reinit_firmware(struct net_d
1409          return err;          return err;
1410  }  }
1411    
1412  static int orinoco_open(struct net_device *dev)  static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)
1413  {  {
1414          struct orinoco_private *priv = dev->priv;          hermes_t *hw = &priv->hw;
1415          unsigned long flags;          int err = 0;
         int err;  
1416    
1417          err = orinoco_lock(priv, &flags);          if (priv->bitratemode >= BITRATE_TABLE_SIZE) {
1418          if (err)                  printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
1419                  return err;                         priv->ndev->name, priv->bitratemode);
1420                    return -EINVAL;
1421            }
1422    
1423          err = __orinoco_up(dev);          switch (priv->firmware_type) {
1424            case FIRMWARE_TYPE_AGERE:
1425                    err = hermes_write_wordrec(hw, USER_BAP,
1426                                               HERMES_RID_CNFTXRATECONTROL,
1427                                               bitrate_table[priv->bitratemode].agere_txratectrl);
1428                    break;
1429            case FIRMWARE_TYPE_INTERSIL:
1430            case FIRMWARE_TYPE_SYMBOL:
1431                    err = hermes_write_wordrec(hw, USER_BAP,
1432                                               HERMES_RID_CNFTXRATECONTROL,
1433                                               bitrate_table[priv->bitratemode].intersil_txratectrl);
1434                    break;
1435            default:
1436                    BUG();
1437            }
1438    
1439          if (! err)          return err;
1440                  priv->open = 1;  }
1441    
1442          orinoco_unlock(priv, &flags);  /* Just switch the WEP key, without changing other WEP/authentication
1443     * parameters.  Used on firmware that can handle it to switch the key
1444     * without breaking the association, which is necessary for 802.1x */
1445    static int __orinoco_fastkeychange(struct orinoco_private *priv)
1446    {
1447            hermes_t *hw = &priv->hw;
1448            int err = 0;
1449    
1450          return err;          if (! priv->wep_on) {
1451                    printk(KERN_DEBUG "%s: __orinoco_fastkeychange while WEP disabled!?\n",
1452                           priv->ndev->name);
1453                    return 0;
1454            }
1455    
1456            if (! priv->has_fastkeychange)
1457                    return -EAGAIN;
1458    
1459            switch (priv->firmware_type) {
1460            case FIRMWARE_TYPE_AGERE:
1461                    err = HERMES_WRITE_RECORD(hw, USER_BAP,
1462                                              HERMES_RID_CNFWEPKEYS_AGERE,
1463                                              &priv->keys);
1464                    if (err)
1465                            return err;
1466                    err = hermes_write_wordrec(hw, USER_BAP,
1467                                               HERMES_RID_CNFTXKEY_AGERE,
1468                                               priv->tx_key);
1469                    if (err)
1470                            return err;
1471                    break;
1472            case FIRMWARE_TYPE_INTERSIL:
1473            case FIRMWARE_TYPE_SYMBOL:
1474                    /* FIXME: do any non-Agere firmwares support fast key
1475                     * change? */
1476                    return -EAGAIN;
1477                    break;
1478            }
1479    
1480            return 0;
1481  }  }
1482    
1483  int orinoco_stop(struct net_device *dev)  static int __orinoco_hw_setup_wep(struct orinoco_private *priv)
1484  {  {
1485          struct orinoco_private *priv = dev->priv;          hermes_t *hw = &priv->hw;
1486          int err = 0;          int err = 0;
1487            int master_wep_flag;
1488            int auth_flag;
1489    
1490          /* We mustn't use orinoco_lock() here, because we need to be          switch (priv->firmware_type) {
1491             able to close the interface even if hw_unavailable is set          case FIRMWARE_TYPE_AGERE: /* Agere style WEP */
1492             (e.g. as we're released after a PC Card removal) */                  if (priv->wep_on) {
1493          orinoco_spin_lock(priv);                          /* Enable the shared-key authentication. */
1494                            /* FIXME: We never clear the authentication flag... */
1495                            if (priv->wep_restrict)
1496                                    auth_flag = 0x2;
1497                            else
1498                                    auth_flag = 0x0;
1499                            err = hermes_write_wordrec(hw, USER_BAP,
1500                                                       HERMES_RID_CNFAUTHENTICATION_AGERE,
1501                                                       auth_flag);          
1502                            if (err)
1503                                    return err;
1504                            err = hermes_write_wordrec(hw, USER_BAP,
1505                                                       HERMES_RID_CNFTXKEY_AGERE,
1506                                                       priv->tx_key);
1507                            if (err)
1508                                    return err;
1509                            
1510                            err = HERMES_WRITE_RECORD(hw, USER_BAP,
1511                                                      HERMES_RID_CNFWEPKEYS_AGERE,
1512                                                      &priv->keys);
1513                            if (err)
1514                                    return err;
1515                    }
1516                    err = hermes_write_wordrec(hw, USER_BAP,
1517                                               HERMES_RID_CNFWEPENABLED_AGERE,
1518                                               priv->wep_on);
1519                    if (err)
1520                            return err;
1521                    break;
1522    
1523          priv->open = 0;          case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */
1524            case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */
1525                    master_wep_flag = 0;            /* Off */
1526                    if (priv->wep_on) {
1527                            int keylen;
1528                            int i;
1529    
1530          err = __orinoco_down(dev);                          /* Fudge around firmware weirdness */
1531                            keylen = le16_to_cpu(priv->keys[priv->tx_key].len);
1532                            
1533                            /* Write all 4 keys */
1534                            for(i = 0; i < ORINOCO_MAX_KEYS; i++) {
1535    /*                              int keylen = le16_to_cpu(priv->keys[i].len); */
1536                                    
1537                                    if (keylen > LARGE_KEY_SIZE) {
1538                                            printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
1539                                                   priv->ndev->name, i, keylen);
1540                                            return -E2BIG;
1541                                    }
1542    
1543          orinoco_spin_unlock(priv);                                  err = hermes_write_ltv(hw, USER_BAP,
1544                                                           HERMES_RID_CNFDEFAULTKEY0 + i,
1545                                                           HERMES_BYTES_TO_RECLEN(keylen),
1546                                                           priv->keys[i].data);
1547                                    if (err)
1548                                            return err;
1549                            }
1550    
1551          return err;                          /* Write the index of the key used in transmission */
1552                            err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFWEPDEFAULTKEYID,
1553                                                       priv->tx_key);
1554                            if (err)
1555                                    return err;
1556                            
1557                            if (priv->wep_restrict) {
1558                                    auth_flag = 2;
1559                                    master_wep_flag = 3;
1560                            } else {
1561                                    /* Authentication is where Intersil and Symbol
1562                                     * firmware differ... */
1563                                    auth_flag = 1;
1564                                    if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
1565                                            master_wep_flag = 3; /* Symbol */
1566                                    else
1567                                            master_wep_flag = 1; /* Intersil */
1568                            }
1569    
1570    
1571                            err = hermes_write_wordrec(hw, USER_BAP,
1572                                                       HERMES_RID_CNFAUTHENTICATION, auth_flag);
1573                            if (err)
1574                                    return err;
1575                    }
1576                    
1577                    /* Master WEP setting : on/off */
1578                    err = hermes_write_wordrec(hw, USER_BAP,
1579                                               HERMES_RID_CNFWEPFLAGS_INTERSIL,
1580                                               master_wep_flag);
1581                    if (err)
1582                            return err;    
1583    
1584                    break;
1585    
1586            default:
1587                    if (priv->wep_on) {
1588                            printk(KERN_ERR "%s: WEP enabled, although not supported!\n",
1589                                   priv->ndev->name);
1590                            return -EINVAL;
1591                    }
1592            }
1593    
1594            return 0;
1595  }  }
1596    
1597  static int __orinoco_program_rids(struct net_device *dev)  static int __orinoco_program_rids(struct net_device *dev)
# Line 939  ESSID in IBSS-Ad-Hoc mode.\n", dev->name Line 1802  ESSID in IBSS-Ad-Hoc mode.\n", dev->name
1802          return 0;          return 0;
1803  }  }
1804    
1805  /* xyzzy */  /* FIXME: return int? */
1806  static int orinoco_reconfigure(struct net_device *dev)  static void
1807    __orinoco_set_multicast_list(struct net_device *dev)
1808  {  {
1809          struct orinoco_private *priv = dev->priv;          struct orinoco_private *priv = dev->priv;
1810          struct hermes *hw = &priv->hw;          hermes_t *hw = &priv->hw;
         unsigned long flags;  
1811          int err = 0;          int err = 0;
1812            int promisc, mc_count;
1813    
1814          if (priv->broken_disableport) {          /* The Hermes doesn't seem to have an allmulti mode, so we go
1815                  schedule_work(&priv->reset_work);           * into promiscuous mode and let the upper levels deal. */
1816                  return 0;          if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||
1817                 (dev->mc_count > MAX_MULTICAST(priv)) ) {
1818                    promisc = 1;
1819                    mc_count = 0;
1820            } else {
1821                    promisc = 0;
1822                    mc_count = dev->mc_count;
1823          }          }
1824    
1825          err = orinoco_lock(priv, &flags);          if (promisc != priv->promiscuous) {
1826          if (err)                  err = hermes_write_wordrec(hw, USER_BAP,
1827                  return err;                                             HERMES_RID_CNFPROMISCUOUSMODE,
1828                                               promisc);
1829                                    if (err) {
1830          err = hermes_disable_port(hw, 0);                          printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",
1831          if (err) {                                 dev->name, err);
1832                  printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n",                  } else
1833                         dev->name);                          priv->promiscuous = promisc;
                 priv->broken_disableport = 1;  
                 goto out;  
1834          }          }
1835    
1836          err = __orinoco_program_rids(dev);          if (! promisc && (mc_count || priv->mc_count) ) {
1837          if (err) {                  struct dev_mc_list *p = dev->mc_list;
1838                  printk(KERN_WARNING "%s: Unable to reconfigure card\n",                  hermes_multicast_t mclist;
1839                         dev->name);                  int i;
                 goto out;  
         }  
1840    
1841          err = hermes_enable_port(hw, 0);                  for (i = 0; i < mc_count; i++) {
1842          if (err) {                          /* paranoia: is list shorter than mc_count? */
1843                  printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",                          BUG_ON(! p);
1844                         dev->name);                          /* paranoia: bad address size in list? */
1845                  goto out;                          BUG_ON(p->dmi_addrlen != ETH_ALEN);
1846          }                          
1847                            memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);
1848                            p = p->next;
1849                    }
1850                    
1851                    if (p)
1852                            printk(KERN_WARNING "Multicast list is longer than mc_count\n");
1853    
1854   out:                  err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,
1855          if (err) {                                         HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),
1856                  printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);                                         &mclist);
1857                  schedule_work(&priv->reset_work);                  if (err)
1858                  err = 0;                          printk(KERN_ERR "%s: Error %d setting multicast list.\n",
1859                                   dev->name, err);
1860                    else
1861                            priv->mc_count = mc_count;
1862          }          }
1863    
1864          orinoco_unlock(priv, &flags);          /* Since we can set the promiscuous flag when it wasn't asked
1865          return err;             for, make sure the net_device knows about it. */
1866            if (priv->promiscuous)
1867                    dev->flags |= IFF_PROMISC;
1868            else
1869                    dev->flags &= ~IFF_PROMISC;
1870  }  }
1871    
1872  /* This must be called from user context, without locks held - use  /* This must be called from user context, without locks held - use
# Line 1056  static void orinoco_reset(struct net_dev Line 1934  static void orinoco_reset(struct net_dev
1934  }  }
1935    
1936  /********************************************************************/  /********************************************************************/
1937  /* Internal helper functions                                        */  /* Interrupt handler                                                */
 /********************************************************************/  
   
 static inline void  
 set_port_type(struct orinoco_private *priv)  
 {  
         switch (priv->iw_mode) {  
         case IW_MODE_INFRA:  
                 priv->port_type = 1;  
                 priv->createibss = 0;  
                 break;  
         case IW_MODE_ADHOC:  
                 if (priv->prefer_port3) {  
                         priv->port_type = 3;  
                         priv->createibss = 0;  
                 } else {  
                         priv->port_type = priv->ibss_port;  
                         priv->createibss = 1;  
                 }  
                 break;  
         default:  
                 printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",  
                        priv->ndev->name);  
         }  
 }  
   
 /* Does the frame have a SNAP header indicating it should be  
  * de-encapsulated to Ethernet-II? */  
 static inline int  
 is_ethersnap(struct header_struct *hdr)  
 {  
         /* We de-encapsulate all packets which, a) have SNAP headers  
          * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header  
          * and where b) the OUI of the SNAP header is 00:00:00 or  
          * 00:00:f8 - we need both because different APs appear to use  
          * different OUIs for some reason */  
         return (memcmp(&hdr->dsap, &encaps_hdr, 5) == 0)  
                 && ( (hdr->oui[2] == 0x00) || (hdr->oui[2] == 0xf8) );  
 }  
   
 static void  
 orinoco_set_multicast_list(struct net_device *dev)  
 {  
         struct orinoco_private *priv = dev->priv;  
         unsigned long flags;  
   
         if (orinoco_lock(priv, &flags) != 0) {  
                 printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "  
                        "called when hw_unavailable\n", dev->name);  
                 return;  
         }  
   
         __orinoco_set_multicast_list(dev);  
         orinoco_unlock(priv, &flags);  
 }  
   
 /********************************************************************/  
 /* Hardware control functions                                       */  
1938  /********************************************************************/  /********************************************************************/
1939    
1940    static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)
 static int __orinoco_hw_set_bitrate(struct orinoco_private *priv)  
 {  
         hermes_t *hw = &priv->hw;  
         int err = 0;  
   
         if (priv->bitratemode >= BITRATE_TABLE_SIZE) {  
                 printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",  
                        priv->ndev->name, priv->bitratemode);  
                 return -EINVAL;  
         }  
   
         switch (priv->firmware_type) {  
         case FIRMWARE_TYPE_AGERE:  
                 err = hermes_write_wordrec(hw, USER_BAP,  
                                            HERMES_RID_CNFTXRATECONTROL,  
                                            bitrate_table[priv->bitratemode].agere_txratectrl);  
                 break;  
         case FIRMWARE_TYPE_INTERSIL:  
         case FIRMWARE_TYPE_SYMBOL:  
                 err = hermes_write_wordrec(hw, USER_BAP,  
                                            HERMES_RID_CNFTXRATECONTROL,  
                                            bitrate_table[priv->bitratemode].intersil_txratectrl);  
                 break;  
         default:  
                 BUG();  
         }  
   
         return err;  
 }  
   
 /* Just switch the WEP key, without changing other WEP/authentication  
  * parameters.  Used on firmware that can handle it to switch the key  
  * without breaking the association, which is necessary for 802.1x */  
 static int __orinoco_fastkeychange(struct orinoco_private *priv)  
 {  
         hermes_t *hw = &priv->hw;  
         int err = 0;  
   
         if (! priv->wep_on) {  
                 printk(KERN_DEBUG "%s: __orinoco_fastkeychange while WEP disabled!?\n",  
                        priv->ndev->name);  
                 return 0;  
         }  
   
         if (! priv->has_fastkeychange)  
                 return -EAGAIN;  
   
         switch (priv->firmware_type) {  
         case FIRMWARE_TYPE_AGERE:  
                 err = HERMES_WRITE_RECORD(hw, USER_BAP,  
                                           HERMES_RID_CNFWEPKEYS_AGERE,  
                                           &priv->keys);  
                 if (err)  
                         return err;  
                 err = hermes_write_wordrec(hw, USER_BAP,  
                                            HERMES_RID_CNFTXKEY_AGERE,  
                                            priv->tx_key);  
                 if (err)  
                         return err;  
                 break;  
         case FIRMWARE_TYPE_INTERSIL:  
         case FIRMWARE_TYPE_SYMBOL:  
                 /* FIXME: do any non-Agere firmwares support fast key  
                  * change? */  
                 return -EAGAIN;  
                 break;  
         }  
   
         return 0;  
 }  
   
 static int __orinoco_hw_setup_wep(struct orinoco_private *priv)  
 {  
         hermes_t *hw = &priv->hw;  
         int err = 0;  
         int master_wep_flag;  
         int auth_flag;  
   
         switch (priv->firmware_type) {  
         case FIRMWARE_TYPE_AGERE: /* Agere style WEP */  
                 if (priv->wep_on) {  
                         /* Enable the shared-key authentication. */  
                         /* FIXME: We never clear the authentication flag... */  
                         if (priv->wep_restrict)  
                                 auth_flag = 0x2;  
                         else  
                                 auth_flag = 0x0;  
                         err = hermes_write_wordrec(hw, USER_BAP,  
                                                    HERMES_RID_CNFAUTHENTICATION_AGERE,  
                                                    auth_flag);            
                         if (err)  
                                 return err;  
                         err = hermes_write_wordrec(hw, USER_BAP,  
                                                    HERMES_RID_CNFTXKEY_AGERE,  
                                                    priv->tx_key);  
                         if (err)  
                                 return err;  
                           
                         err = HERMES_WRITE_RECORD(hw, USER_BAP,  
                                                   HERMES_RID_CNFWEPKEYS_AGERE,  
                                                   &priv->keys);  
                         if (err)  
                                 return err;  
                 }  
                 err = hermes_write_wordrec(hw, USER_BAP,  
                                            HERMES_RID_CNFWEPENABLED_AGERE,  
                                            priv->wep_on);  
                 if (err)  
                         return err;  
                 break;  
   
         case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */  
         case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */  
                 master_wep_flag = 0;            /* Off */  
                 if (priv->wep_on) {  
                         int keylen;  
                         int i;  
   
                         /* Fudge around firmware weirdness */  
                         keylen = le16_to_cpu(priv->keys[priv->tx_key].len);  
                           
                         /* Write all 4 keys */  
                         for(i = 0; i < ORINOCO_MAX_KEYS; i++) {  
 /*                              int keylen = le16_to_cpu(priv->keys[i].len); */  
                                   
                                 if (keylen > LARGE_KEY_SIZE) {  
                                         printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",  
                                                priv->ndev->name, i, keylen);  
                                         return -E2BIG;  
                                 }  
   
                                 err = hermes_write_ltv(hw, USER_BAP,  
                                                        HERMES_RID_CNFDEFAULTKEY0 + i,  
                                                        HERMES_BYTES_TO_RECLEN(keylen),  
                                                        priv->keys[i].data);  
                                 if (err)  
                                         return err;  
                         }  
   
                         /* Write the index of the key used in transmission */  
                         err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFWEPDEFAULTKEYID,  
                                                    priv->tx_key);  
                         if (err)  
                                 return err;  
                           
                         if (priv->wep_restrict) {  
                                 auth_flag = 2;  
                                 master_wep_flag = 3;  
                         } else {  
                                 /* Authentication is where Intersil and Symbol  
                                  * firmware differ... */  
                                 auth_flag = 1;  
                                 if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)  
                                         master_wep_flag = 3; /* Symbol */  
                                 else  
                                         master_wep_flag = 1; /* Intersil */  
                         }  
   
   
                         err = hermes_write_wordrec(hw, USER_BAP,  
                                                    HERMES_RID_CNFAUTHENTICATION, auth_flag);  
                         if (err)  
                                 return err;  
                 }  
                   
                 /* Master WEP setting : on/off */  
                 err = hermes_write_wordrec(hw, USER_BAP,  
                                            HERMES_RID_CNFWEPFLAGS_INTERSIL,  
                                            master_wep_flag);  
                 if (err)  
                         return err;      
   
                 break;  
   
         default:  
                 if (priv->wep_on) {  
                         printk(KERN_ERR "%s: WEP enabled, although not supported!\n",  
                                priv->ndev->name);  
                         return -EINVAL;  
                 }  
         }  
   
         return 0;  
 }  
   
 static int orinoco_hw_get_bssid(struct orinoco_private *priv,  
                                 char buf[ETH_ALEN])  
 {  
         hermes_t *hw = &priv->hw;  
         int err = 0;  
         unsigned long flags;  
   
         err = orinoco_lock(priv, &flags);  
         if (err)  
                 return err;  
   
         err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,  
                               ETH_ALEN, NULL, buf);  
   
         orinoco_unlock(priv, &flags);  
   
         return err;  
 }  
   
 static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,  
                                 char buf[IW_ESSID_MAX_SIZE+1])  
 {  
         hermes_t *hw = &priv->hw;  
         int err = 0;  
         struct hermes_idstring essidbuf;  
         char *p = (char *)(&essidbuf.val);  
         int len;  
         unsigned long flags;  
   
         err = orinoco_lock(priv, &flags);  
         if (err)  
                 return err;  
   
         if (strlen(priv->desired_essid) > 0) {  
                 /* We read the desired SSID from the hardware rather  
                    than from priv->desired_essid, just in case the  
                    firmware is allowed to change it on us. I'm not  
                    sure about this */  
                 /* My guess is that the OWNSSID should always be whatever  
                  * we set to the card, whereas CURRENT_SSID is the one that  
                  * may change... - Jean II */  
                 u16 rid;  
   
                 *active = 1;  
   
                 rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :  
                         HERMES_RID_CNFDESIREDSSID;  
                   
                 err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),  
                                       NULL, &essidbuf);  
                 if (err)  
                         goto fail_unlock;  
         } else {  
                 *active = 0;  
   
                 err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,  
                                       sizeof(essidbuf), NULL, &essidbuf);  
                 if (err)  
                         goto fail_unlock;  
         }  
   
         len = le16_to_cpu(essidbuf.len);  
         BUG_ON(len > IW_ESSID_MAX_SIZE);  
   
         memset(buf, 0, IW_ESSID_MAX_SIZE+1);  
         memcpy(buf, p, len);  
         buf[len] = '\0';  
   
  fail_unlock:  
         orinoco_unlock(priv, &flags);  
   
         return err;        
 }  
   
 static long orinoco_hw_get_freq(struct orinoco_private *priv)  
 {  
           
         hermes_t *hw = &priv->hw;  
         int err = 0;  
         u16 channel;  
         long freq = 0;  
         unsigned long flags;  
   
         err = orinoco_lock(priv, &flags);  
         if (err)  
                 return err;  
           
         err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel);  
         if (err)  
                 goto out;  
   
         /* Intersil firmware 1.3.5 returns 0 when the interface is down */  
         if (channel == 0) {  
                 err = -EBUSY;  
                 goto out;  
         }  
   
         if ( (channel < 1) || (channel > NUM_CHANNELS) ) {  
                 printk(KERN_WARNING "%s: Channel out of range (%d)!\n",  
                        priv->ndev->name, channel);  
                 err = -EBUSY;  
                 goto out;  
   
         }  
         freq = channel_frequency[channel-1] * 100000;  
   
  out:  
         orinoco_unlock(priv, &flags);  
   
         if (err > 0)  
                 err = -EBUSY;  
         return err ? err : freq;  
 }  
   
 static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,  
                                       int *numrates, s32 *rates, int max)  
1941  {  {
1942          hermes_t *hw = &priv->hw;          printk(KERN_DEBUG "%s: TICK\n", dev->name);
         struct hermes_idstring list;  
         unsigned char *p = (unsigned char *)&list.val;  
         int err = 0;  
         int num;  
         int i;  
         unsigned long flags;  
   
         err = orinoco_lock(priv, &flags);  
         if (err)  
                 return err;  
   
         err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,  
                               sizeof(list), NULL, &list);  
         orinoco_unlock(priv, &flags);  
   
         if (err)  
                 return err;  
           
         num = le16_to_cpu(list.len);  
         *numrates = num;  
         num = min(num, max);  
   
         for (i = 0; i < num; i++) {  
                 rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */  
         }  
   
         return 0;  
1943  }  }
1944    
1945  #if 0  static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)
 static void show_rx_frame(struct orinoco_rxframe_hdr *frame)  
1946  {  {
1947          printk(KERN_DEBUG "RX descriptor:\n");          /* This seems to happen a fair bit under load, but ignoring it
1948          printk(KERN_DEBUG "  status      = 0x%04x\n", frame->desc.status);             seems to work fine...*/
1949          printk(KERN_DEBUG "  time        = 0x%08x\n", frame->desc.time);          printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
1950          printk(KERN_DEBUG "  silence     = 0x%02x\n", frame->desc.silence);                 dev->name);
         printk(KERN_DEBUG "  signal      = 0x%02x\n", frame->desc.signal);  
         printk(KERN_DEBUG "  rate        = 0x%02x\n", frame->desc.rate);  
         printk(KERN_DEBUG "  rxflow      = 0x%02x\n", frame->desc.rxflow);  
         printk(KERN_DEBUG "  reserved    = 0x%08x\n", frame->desc.reserved);  
   
         printk(KERN_DEBUG "IEEE 802.11 header:\n");  
         printk(KERN_DEBUG "  frame_ctl   = 0x%04x\n",  
                frame->p80211.frame_ctl);  
         printk(KERN_DEBUG "  duration_id = 0x%04x\n",  
                frame->p80211.duration_id);  
         printk(KERN_DEBUG "  addr1       = %02x:%02x:%02x:%02x:%02x:%02x\n",  
                frame->p80211.addr1[0], frame->p80211.addr1[1],  
                frame->p80211.addr1[2], frame->p80211.addr1[3],  
                frame->p80211.addr1[4], frame->p80211.addr1[5]);  
         printk(KERN_DEBUG "  addr2       = %02x:%02x:%02x:%02x:%02x:%02x\n",  
                frame->p80211.addr2[0], frame->p80211.addr2[1],  
                frame->p80211.addr2[2], frame->p80211.addr2[3],  
                frame->p80211.addr2[4], frame->p80211.addr2[5]);  
         printk(KERN_DEBUG "  addr3       = %02x:%02x:%02x:%02x:%02x:%02x\n",  
                frame->p80211.addr3[0], frame->p80211.addr3[1],  
                frame->p80211.addr3[2], frame->p80211.addr3[3],  
                frame->p80211.addr3[4], frame->p80211.addr3[5]);  
         printk(KERN_DEBUG "  seq_ctl     = 0x%04x\n",  
                frame->p80211.seq_ctl);  
         printk(KERN_DEBUG "  addr4       = %02x:%02x:%02x:%02x:%02x:%02x\n",  
                frame->p80211.addr4[0], frame->p80211.addr4[1],  
                frame->p80211.addr4[2], frame->p80211.addr4[3],  
                frame->p80211.addr4[4], frame->p80211.addr4[5]);  
         printk(KERN_DEBUG "  data_len    = 0x%04x\n",  
                frame->p80211.data_len);  
   
         printk(KERN_DEBUG "IEEE 802.3 header:\n");  
         printk(KERN_DEBUG "  dest        = %02x:%02x:%02x:%02x:%02x:%02x\n",  
                frame->p8023.h_dest[0], frame->p8023.h_dest[1],  
                frame->p8023.h_dest[2], frame->p8023.h_dest[3],  
                frame->p8023.h_dest[4], frame->p8023.h_dest[5]);  
         printk(KERN_DEBUG "  src         = %02x:%02x:%02x:%02x:%02x:%02x\n",  
                frame->p8023.h_source[0], frame->p8023.h_source[1],  
                frame->p8023.h_source[2], frame->p8023.h_source[3],  
                frame->p8023.h_source[4], frame->p8023.h_source[5]);  
         printk(KERN_DEBUG "  len         = 0x%04x\n", frame->p8023.h_proto);  
   
         printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");  
         printk(KERN_DEBUG "  DSAP        = 0x%02x\n", frame->p8022.dsap);  
         printk(KERN_DEBUG "  SSAP        = 0x%02x\n", frame->p8022.ssap);  
         printk(KERN_DEBUG "  ctrl        = 0x%02x\n", frame->p8022.ctrl);  
         printk(KERN_DEBUG "  OUI         = %02x:%02x:%02x\n",  
                frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);  
         printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);  
1951  }  }
 #endif /* 0 */  
1952    
 /*  
  * Interrupt handler  
  */  
1953  irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)  irqreturn_t orinoco_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1954  {  {
1955          struct net_device *dev = (struct net_device *)dev_id;          struct net_device *dev = (struct net_device *)dev_id;
# Line 1586  irqreturn_t orinoco_interrupt(int irq, v Line 2025  irqreturn_t orinoco_interrupt(int irq, v
2025          return IRQ_HANDLED;          return IRQ_HANDLED;
2026  }  }
2027    
2028  static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw)  /********************************************************************/
2029  {  /* Initialization                                                   */
2030          printk(KERN_DEBUG "%s: TICK\n", dev->name);  /********************************************************************/
 }  
   
 static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw)  
 {  
         /* This seems to happen a fair bit under load, but ignoring it  
            seems to work fine...*/  
         printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",  
                dev->name);  
 }  
   
 static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw)  
 {  
         printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name);  
 }  
   
 static void print_linkstatus(struct net_device *dev, u16 status)  
 {  
         char * s;  
   
         if (suppress_linkstatus)  
                 return;  
   
         switch (status) {  
         case HERMES_LINKSTATUS_NOT_CONNECTED:  
                 s = "Not Connected";  
                 break;  
         case HERMES_LINKSTATUS_CONNECTED:  
                 s = "Connected";  
                 break;  
         case HERMES_LINKSTATUS_DISCONNECTED:  
                 s = "Disconnected";  
                 break;  
         case HERMES_LINKSTATUS_AP_CHANGE:  
                 s = "AP Changed";  
                 break;  
         case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:  
                 s = "AP Out of Range";  
                 break;  
         case HERMES_LINKSTATUS_AP_IN_RANGE:  
                 s = "AP In Range";  
                 break;  
         case HERMES_LINKSTATUS_ASSOC_FAILED:  
                 s = "Association Failed";  
                 break;  
         default:  
                 s = "UNKNOWN";  
         }  
           
         printk(KERN_INFO "%s: New link status: %s (%04x)\n",  
                dev->name, s, status);  
 }  
   
 void __orinoco_ev_info(struct net_device *dev, hermes_t *hw)  
 {  
         struct orinoco_private *priv = dev->priv;  
         u16 infofid;  
         struct {  
                 u16 len;  
                 u16 type;  
         } __attribute__ ((packed)) info;  
         int len, type;  
         int err;  
   
         /* This is an answer to an INQUIRE command that we did earlier,  
          * or an information "event" generated by the card  
          * The controller return to us a pseudo frame containing  
          * the information in question - Jean II */  
         infofid = hermes_read_regn(hw, INFOFID);  
   
         /* Read the info frame header - don't try too hard */  
         err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),  
                                infofid, 0);  
         if (err) {  
                 printk(KERN_ERR "%s: error %d reading info frame. "  
                        "Frame dropped.\n", dev->name, err);  
                 return;  
         }  
           
         len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len));  
         type = le16_to_cpu(info.type);  
   
         switch (type) {  
         case HERMES_INQ_TALLIES: {  
                 struct hermes_tallies_frame tallies;  
                 struct iw_statistics *wstats = &priv->wstats;  
                   
                 if (len > sizeof(tallies)) {  
                         printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n",  
                                dev->name, len);  
                         len = sizeof(tallies);  
                 }  
                   
                 /* Read directly the data (no seek) */  
                 /* FIXME: blech! ??? */  
                 hermes_bap_pread(hw, IRQ_BAP, &tallies, len, infofid, sizeof(info));  
   
                 /* Increment our various counters */  
                 /* wstats->discard.nwid - no wrong BSSID stuff */  
                 wstats->discard.code +=  
                         le16_to_cpu(tallies.RxWEPUndecryptable);  
                 if (len == sizeof(tallies))    
                         wstats->discard.code +=  
                                 le16_to_cpu(tallies.RxDiscards_WEPICVError) +  
                                 le16_to_cpu(tallies.RxDiscards_WEPExcluded);  
                 wstats->discard.misc +=  
                         le16_to_cpu(tallies.TxDiscardsWrongSA);  
 #if WIRELESS_EXT > 11  
                 wstats->discard.fragment +=  
                         le16_to_cpu(tallies.RxMsgInBadMsgFragments);  
                 wstats->discard.retries +=  
                         le16_to_cpu(tallies.TxRetryLimitExceeded);  
                 /* wstats->miss.beacon - no match */  
 #endif /* WIRELESS_EXT > 11 */  
         }  
         break;  
         case HERMES_INQ_LINKSTATUS: {  
                 struct hermes_linkstatus linkstatus;  
                 u16 newstatus;  
                   
                 if (len != sizeof(linkstatus)) {  
                         printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",  
                                dev->name, len);  
                         break;  
                 }  
   
                 hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len, infofid, sizeof(info));  
   
                 newstatus = le16_to_cpu(linkstatus.linkstatus);  
   
                 if ( (newstatus == HERMES_LINKSTATUS_CONNECTED)  
                      || (newstatus == HERMES_LINKSTATUS_AP_CHANGE)  
                      || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE) )  
                         netif_carrier_on(dev);  
                 else if ( (newstatus == HERMES_LINKSTATUS_NOT_CONNECTED)  
                           || (newstatus == HERMES_LINKSTATUS_DISCONNECTED)  
                           || (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE)  
                           || (newstatus == HERMES_LINKSTATUS_ASSOC_FAILED) )  
                         netif_carrier_off(dev);  
   
                 if (newstatus != priv->last_linkstatus)  
                         print_linkstatus(dev, newstatus);  
   
                 priv->last_linkstatus = newstatus;  
         }  
         break;  
         default:  
                 printk(KERN_DEBUG "%s: Unknown information frame received (type %04x).\n",  
                       dev->name, type);  
                 /* We don't actually do anything about it */  
                 break;  
         }  
 }  
   
 void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw)  
 {  
         struct orinoco_private *priv = dev->priv;  
         struct net_device_stats *stats = &priv->stats;  
         struct iw_statistics *wstats = &priv->wstats;  
         struct sk_buff *skb = NULL;  
         u16 rxfid, status;  
         int length, data_len, data_off;  
         char *p;  
         struct hermes_rx_descriptor desc;  
         struct header_struct hdr;  
         struct ethhdr *eh;  
         int err;  
   
         rxfid = hermes_read_regn(hw, RXFID);  
   
         err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc),  
                                rxfid, 0);  
         if (err) {  
                 printk(KERN_ERR "%s: error %d reading Rx descriptor. "  
                        "Frame dropped.\n", dev->name, err);  
                 stats->rx_errors++;  
                 goto drop;  
         }  
   
         status = le16_to_cpu(desc.status);  
           
         if (status & HERMES_RXSTAT_ERR) {  
                 if (status & HERMES_RXSTAT_UNDECRYPTABLE) {  
                         wstats->discard.code++;  
                         DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",  
                                dev->name);  
                 } else {  
                         stats->rx_crc_errors++;  
                         DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);  
                 }  
                 stats->rx_errors++;  
                 goto drop;  
         }  
   
         /* For now we ignore the 802.11 header completely, assuming  
            that the card's firmware has handled anything vital */  
   
         err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr),  
                                rxfid, HERMES_802_3_OFFSET);  
         if (err) {  
                 printk(KERN_ERR "%s: error %d reading frame header. "  
                        "Frame dropped.\n", dev->name, err);  
                 stats->rx_errors++;  
                 goto drop;  
         }  
   
         length = ntohs(hdr.len);  
           
         /* Sanity checks */  
         if (length < 3) { /* No for even an 802.2 LLC header */  
                 /* At least on Symbol firmware with PCF we get quite a  
                    lot of these legitimately - Poll frames with no  
                    data. */  
                 stats->rx_dropped++;  
                 goto drop;  
         }  
         if (length > IEEE802_11_DATA_LEN) {  
                 printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",  
                        dev->name, length);  
                 stats->rx_length_errors++;  
                 stats->rx_errors++;  
                 goto drop;  
         }  
   
         /* We need space for the packet data itself, plus an ethernet  
            header, plus 2 bytes so we can align the IP header on a  
            32bit boundary, plus 1 byte so we can read in odd length  
            packets from the card, which has an IO granularity of 16  
            bits */    
         skb = dev_alloc_skb(length+ETH_HLEN+2+1);  
         if (!skb) {  
                 printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",  
                        dev->name);  
                 goto drop;  
         }  
   
         skb_reserve(skb, 2); /* This way the IP header is aligned */  
   
         /* Handle decapsulation  
          * In most cases, the firmware tell us about SNAP frames.  
          * For some reason, the SNAP frames sent by LinkSys APs  
          * are not properly recognised by most firmwares.  
          * So, check ourselves */  
         if(((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) ||  
            ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) ||  
            is_ethersnap(&hdr)) {  
                 /* These indicate a SNAP within 802.2 LLC within  
                    802.11 frame which we'll need to de-encapsulate to  
                    the original EthernetII frame. */  
   
                 if (length < ENCAPS_OVERHEAD) { /* No room for full LLC+SNAP */  
                         stats->rx_length_errors++;  
                         goto drop;  
                 }  
   
                 /* Remove SNAP header, reconstruct EthernetII frame */  
                 data_len = length - ENCAPS_OVERHEAD;  
                 data_off = HERMES_802_3_OFFSET + sizeof(hdr);  
   
                 eh = (struct ethhdr *)skb_put(skb, ETH_HLEN);  
   
                 memcpy(eh, &hdr, 2 * ETH_ALEN);  
                 eh->h_proto = hdr.ethertype;  
         } else {  
                 /* All other cases indicate a genuine 802.3 frame.  No  
                    decapsulation needed.  We just throw the whole  
                    thing in, and hope the protocol layer can deal with  
                    it as 802.3 */  
                 data_len = length;  
                 data_off = HERMES_802_3_OFFSET;  
                 /* FIXME: we re-read from the card data we already read here */  
         }  
   
         p = skb_put(skb, data_len);  
         err = hermes_bap_pread(hw, IRQ_BAP, p, ALIGN(data_len, 2),  
                                rxfid, data_off);  
         if (err) {  
                 printk(KERN_ERR "%s: error %d reading frame. "  
                        "Frame dropped.\n", dev->name, err);  
                 stats->rx_errors++;  
                 goto drop;  
         }  
   
         dev->last_rx = jiffies;  
         skb->dev = dev;  
         skb->protocol = eth_type_trans(skb, dev);  
         skb->ip_summed = CHECKSUM_NONE;  
           
         /* Process the wireless stats if needed */  
         orinoco_stat_gather(dev, skb, &desc);  
   
         /* Pass the packet to the networking stack */  
         netif_rx(skb);  
         stats->rx_packets++;  
         stats->rx_bytes += length;  
   
         return;  
   
  drop:    
         stats->rx_dropped++;  
   
         if (skb)  
                 dev_kfree_skb_irq(skb);  
         return;  
 }  
   
 static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw)  
 {  
         struct orinoco_private *priv = dev->priv;  
         struct net_device_stats *stats = &priv->stats;  
         u16 fid = hermes_read_regn(hw, TXCOMPLFID);  
         struct hermes_tx_descriptor desc;  
         int err = 0;  
   
         if (fid == DUMMY_FID)  
                 return; /* Nothing's really happened */  
   
         err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0);  
         if (err) {  
                 printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "  
                        "(FID=%04X error %d)\n",  
                        dev->name, fid, err);  
         } else {  
                 DEBUG(1, "%s: Tx error, status %d\n",  
                       dev->name, le16_to_cpu(desc.status));  
         }  
           
         stats->tx_errors++;  
   
         hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);  
 }  
   
 static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw)  
 {  
         struct orinoco_private *priv = dev->priv;  
         struct net_device_stats *stats = &priv->stats;  
   
         stats->tx_packets++;  
   
         netif_wake_queue(dev);  
   
         hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);  
 }  
   
 static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw)  
 {  
         struct orinoco_private *priv = dev->priv;  
         u16 fid = hermes_read_regn(hw, ALLOCFID);  
   
         if (fid != priv->txfid) {  
                 if (fid != DUMMY_FID)  
                         printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",  
                                dev->name, fid);  
                 return;  
         }  
   
         hermes_write_regn(hw, ALLOCFID, DUMMY_FID);  
 }  
2031    
2032  struct sta_id {  struct sta_id {
2033          u16 id, variant, major, minor;          u16 id, variant, major, minor;
# Line 2100  static void determine_firmware(struct ne Line 2182  static void determine_firmware(struct ne
2182          }          }
2183  }  }
2184    
2185  /*  static int orinoco_init(struct net_device *dev)
  * struct net_device methods  
  */  
   
 static int  
 orinoco_init(struct net_device *dev)  
2186  {  {
2187          struct orinoco_private *priv = dev->priv;          struct orinoco_private *priv = dev->priv;
2188          hermes_t *hw = &priv->hw;          hermes_t *hw = &priv->hw;
# Line 2287  orinoco_init(struct net_device *dev) Line 2364  orinoco_init(struct net_device *dev)
2364          return err;          return err;
2365  }  }
2366    
2367  struct net_device_stats *  struct net_device *alloc_orinocodev(int sizeof_card,
2368  orinoco_get_stats(struct net_device *dev)                                      int (*hard_reset)(struct orinoco_private *))
2369  {  {
2370          struct orinoco_private *priv = dev->priv;          struct net_device *dev;
2371                    struct orinoco_private *priv;
2372          return &priv->stats;  
2373            dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);
2374            priv = (struct orinoco_private *)dev->priv;
2375            priv->ndev = dev;
2376            if (sizeof_card)
2377                    priv->card = (void *)((unsigned long)dev->priv
2378                                          + sizeof(struct orinoco_private));
2379            else
2380                    priv->card = NULL;
2381    
2382            /* Setup / override net_device fields */
2383            dev->init = orinoco_init;
2384            dev->hard_start_xmit = orinoco_xmit;
2385            dev->tx_timeout = orinoco_tx_timeout;
2386            dev->watchdog_timeo = HZ; /* 1 second timeout */
2387            dev->get_stats = orinoco_get_stats;
2388            dev->get_wireless_stats = orinoco_get_wireless_stats;
2389            dev->do_ioctl = orinoco_ioctl;
2390            dev->change_mtu = orinoco_change_mtu;
2391            dev->set_multicast_list = orinoco_set_multicast_list;
2392            /* we use the default eth_mac_addr for setting the MAC addr */
2393    
2394            /* Set up default callbacks */
2395            dev->open = orinoco_open;
2396            dev->stop = orinoco_stop;
2397            priv->hard_reset = hard_reset;
2398    
2399            spin_lock_init(&priv->lock);
2400            priv->open = 0;
2401            priv->hw_unavailable = 1; /* orinoco_init() must clear this
2402                                       * before anything else touches the
2403                                       * hardware */
2404            INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);
2405    
2406            netif_carrier_off(dev);
2407            priv->last_linkstatus = 0xffff;
2408    
2409            return dev;
2410    
2411  }  }
2412    
2413  struct iw_statistics *  /********************************************************************/
2414  orinoco_get_wireless_stats(struct net_device *dev)  /* Wireless extensions                                              */
2415    /********************************************************************/
2416    
2417    static int orinoco_reconfigure(struct net_device *dev)
2418  {  {
2419          struct orinoco_private *priv = dev->priv;          struct orinoco_private *priv = dev->priv;
2420          hermes_t *hw = &priv->hw;          struct hermes *hw = &priv->hw;
         struct iw_statistics *wstats = &priv->wstats;  
         int err = 0;  
2421          unsigned long flags;          unsigned long flags;
2422            int err = 0;
2423    
2424          if (! netif_device_present(dev)) {          if (priv->broken_disableport) {
2425                  printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n",                  schedule_work(&priv->reset_work);
2426                         dev->name);                  return 0;
                 return NULL; /* FIXME: Can we do better than this? */  
2427          }          }
2428    
2429          err = orinoco_lock(priv, &flags);          err = orinoco_lock(priv, &flags);
2430          if (err)          if (err)
2431                  return NULL; /* FIXME: Erg, we've been signalled, how                  return err;
                               * do we propagate this back up? */  
   
         if (priv->iw_mode == IW_MODE_ADHOC) {  
                 memset(&wstats->qual, 0, sizeof(wstats->qual));  
                 /* If a spy address is defined, we report stats of the  
                  * first spy address - Jean II */  
                 if (SPY_NUMBER(priv)) {  
                         wstats->qual.qual = priv->spy_stat[0].qual;  
                         wstats->qual.level = priv->spy_stat[0].level;  
                         wstats->qual.noise = priv->spy_stat[0].noise;  
                         wstats->qual.updated = priv->spy_stat[0].updated;  
                 }  
         } else {  
                 struct {  
                         u16 qual, signal, noise;  
                 } __attribute__ ((packed)) cq;  
2432    
                 err = HERMES_READ_RECORD(hw, USER_BAP,  
                                          HERMES_RID_COMMSQUALITY, &cq);  
2433                                    
2434                  wstats->qual.qual = (int)le16_to_cpu(cq.qual);          err = hermes_disable_port(hw, 0);
2435                  wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95;          if (err) {
2436                  wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95;                  printk(KERN_WARNING "%s: Unable to disable port while reconfiguring card\n",
2437                  wstats->qual.updated = 7;                         dev->name);
2438                    priv->broken_disableport = 1;
2439                    goto out;
2440          }          }
2441    
2442          /* We can't really wait for the tallies inquiry command to          err = __orinoco_program_rids(dev);
2443           * complete, so we just use the previous results and trigger          if (err) {
2444           * a new tallies inquiry command for next time - Jean II */                  printk(KERN_WARNING "%s: Unable to reconfigure card\n",
2445          /* FIXME: We're in user context (I think?), so we should just                         dev->name);
2446             wait for the tallies to come through */                  goto out;
2447          err = hermes_inquire(hw, HERMES_INQ_TALLIES);          }
                 
         orinoco_unlock(priv, &flags);  
   
         if (err)  
                 return NULL;  
                   
         return wstats;  
 }  
2448    
2449  static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,          err = hermes_enable_port(hw, 0);
2450                                      int level, int noise)          if (err) {
2451  {                  printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
2452          struct orinoco_private *priv = (struct orinoco_private *)dev->priv;                         dev->name);
2453          int i;                  goto out;
2454            }
2455    
2456          /* Gather wireless spy statistics: for each packet, compare the   out:
2457           * source address with out list, and if match, get the stats... */          if (err) {
2458          for (i = 0; i < priv->spy_number; i++)                  printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
2459                  if (!memcmp(mac, priv->spy_address[i], ETH_ALEN)) {                  schedule_work(&priv->reset_work);
2460                          priv->spy_stat[i].level = level - 0x95;                  err = 0;
2461                          priv->spy_stat[i].noise = noise - 0x95;          }
                         priv->spy_stat[i].qual = (level > noise) ? (level - noise) : 0;  
                         priv->spy_stat[i].updated = 7;  
                 }  
 }  
2462    
2463  void          orinoco_unlock(priv, &flags);
2464  orinoco_stat_gather(struct net_device *dev,          return err;
                     struct sk_buff *skb,  
                     struct hermes_rx_descriptor *desc)  
 {  
         struct orinoco_private *priv = (struct orinoco_private *)dev->priv;  
2465    
         /* Using spy support with lots of Rx packets, like in an  
          * infrastructure (AP), will really slow down everything, because  
          * the MAC address must be compared to each entry of the spy list.  
          * If the user really asks for it (set some address in the  
          * spy list), we do it, but he will pay the price.  
          * Note that to get here, you need both WIRELESS_SPY  
          * compiled in AND some addresses in the list !!!  
          */  
         /* Note : gcc will optimise the whole section away if  
          * WIRELESS_SPY is not defined... - Jean II */  
         if (SPY_NUMBER(priv)) {  
                 orinoco_spy_gather(dev, skb->mac.raw + ETH_ALEN,  
                                    desc->signal, desc->silence);  
         }  
2466  }  }
2467    
2468  static int  static int orinoco_hw_get_bssid(struct orinoco_private *priv,
2469  orinoco_xmit(struct sk_buff *skb, struct net_device *dev)                                  char buf[ETH_ALEN])
2470  {  {
         struct orinoco_private *priv = (struct orinoco_private *)dev->priv;  
         struct net_device_stats *stats = &priv->stats;  
2471          hermes_t *hw = &priv->hw;          hermes_t *hw = &priv->hw;
2472          int err = 0;          int err = 0;
         u16 txfid = priv->txfid;  
         char *p;  
         struct ethhdr *eh;  
         int len, data_len, data_off;  
         struct hermes_tx_descriptor desc;  
2473          unsigned long flags;          unsigned long flags;
2474    
2475          TRACE_ENTER(dev->name);          err = orinoco_lock(priv, &flags);
2476            if (err)
2477                    return err;
2478    
2479          if (! netif_running(dev)) {          err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
2480                  printk(KERN_ERR "%s: Tx on stopped device!\n",                                ETH_ALEN, NULL, buf);
                        dev->name);  
                 TRACE_EXIT(dev->name);  
                 return 1;  
         }  
           
         if (netif_queue_stopped(dev)) {  
                 printk(KERN_DEBUG "%s: Tx while transmitter busy!\n",  
                        dev->name);  
                 TRACE_EXIT(dev->name);  
                 return 1;  
         }  
           
         if (orinoco_lock(priv, &flags) != 0) {  
                 printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n",  
                        dev->name);  
                 TRACE_EXIT(dev->name);  
 /*              BUG(); */  
                 return 1;  
         }  
2481    
2482          if (! netif_carrier_ok(dev)) {          orinoco_unlock(priv, &flags);
                 /* Oops, the firmware hasn't established a connection,  
                    silently drop the packet (this seems to be the  
                    safest approach). */  
                 stats->tx_errors++;  
                 orinoco_unlock(priv, &flags);  
                 dev_kfree_skb(skb);  
                 TRACE_EXIT(dev->name);  
                 return 0;  
         }  
2483    
2484          /* Length of the packet body */          return err;
2485          /* FIXME: what if the skb is smaller than this? */  }
         len = max_t(int,skb->len - ETH_HLEN, ETH_ZLEN - ETH_HLEN);  
2486    
2487          eh = (struct ethhdr *)skb->data;  static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
2488                                    char buf[IW_ESSID_MAX_SIZE+1])
2489    {
2490            hermes_t *hw = &priv->hw;
2491            int err = 0;
2492            struct hermes_idstring essidbuf;
2493            char *p = (char *)(&essidbuf.val);
2494            int len;
2495            unsigned long flags;
2496    
2497          memset(&desc, 0, sizeof(desc));          err = orinoco_lock(priv, &flags);
2498          desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);          if (err)
2499          err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);                  return err;
         if (err) {  
                 printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n",  
                        dev->name, err);  
                 stats->tx_errors++;  
                 goto fail;  
         }  
2500    
2501          /* Clear the 802.11 header and data length fields - some          if (strlen(priv->desired_essid) > 0) {
2502           * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused                  /* We read the desired SSID from the hardware rather
2503           * if this isn't done. */                     than from priv->desired_essid, just in case the
2504          hermes_clear_words(hw, HERMES_DATA0,                     firmware is allowed to change it on us. I'm not
2505                             HERMES_802_3_OFFSET - HERMES_802_11_OFFSET);                     sure about this */
2506                    /* My guess is that the OWNSSID should always be whatever
2507                     * we set to the card, whereas CURRENT_SSID is the one that
2508                     * may change... - Jean II */
2509                    u16 rid;
2510    
2511          /* Encapsulate Ethernet-II frames */                  *active = 1;
         if (ntohs(eh->h_proto) > 1500) { /* Ethernet-II frame */  
                 struct header_struct hdr;  
                 data_len = len;  
                 data_off = HERMES_802_3_OFFSET + sizeof(hdr);  
                 p = skb->data + ETH_HLEN;  
2512    
2513                  /* 802.3 header */                  rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID :
2514                  memcpy(hdr.dest, eh->h_dest, ETH_ALEN);                          HERMES_RID_CNFDESIREDSSID;
                 memcpy(hdr.src, eh->h_source, ETH_ALEN);  
                 hdr.len = htons(data_len + ENCAPS_OVERHEAD);  
2515                                    
2516                  /* 802.2 header */                  err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
2517                  memcpy(&hdr.dsap, &encaps_hdr, sizeof(encaps_hdr));                                        NULL, &essidbuf);
2518                                            if (err)
2519                  hdr.ethertype = eh->h_proto;                          goto fail_unlock;
2520                  err  = hermes_bap_pwrite(hw, USER_BAP, &hdr, sizeof(hdr),          } else {
2521                                           txfid, HERMES_802_3_OFFSET);                  *active = 0;
                 if (err) {  
                         printk(KERN_ERR "%s: Error %d writing packet header to BAP\n",  
                                dev->name, err);  
                         stats->tx_errors++;  
                         goto fail;  
                 }  
         } else { /* IEEE 802.3 frame */  
                 data_len = len + ETH_HLEN;  
                 data_off = HERMES_802_3_OFFSET;  
                 p = skb->data;  
         }  
2522    
2523          /* Round up for odd length packets */                  err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
2524          err = hermes_bap_pwrite(hw, USER_BAP, p, ALIGN(data_len, 2),                                        sizeof(essidbuf), NULL, &essidbuf);
2525                                  txfid, data_off);                  if (err)
2526          if (err) {                          goto fail_unlock;
                 printk(KERN_ERR "%s: Error %d writing packet to BAP\n",  
                        dev->name, err);  
                 stats->tx_errors++;  
                 goto fail;  
2527          }          }
2528    
2529          /* Finally, we actually initiate the send */          len = le16_to_cpu(essidbuf.len);
2530          netif_stop_queue(dev);          BUG_ON(len > IW_ESSID_MAX_SIZE);
   
         err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL,  
                                 txfid, NULL);  
         if (err) {  
                 netif_start_queue(dev);  
                 printk(KERN_ERR "%s: Error %d transmitting packet\n",  
                        dev->name, err);  
                 stats->tx_errors++;  
                 goto fail;  
         }  
2531    
2532          dev->trans_start = jiffies;          memset(buf, 0, IW_ESSID_MAX_SIZE+1);
2533          stats->tx_bytes += data_off + data_len;          memcpy(buf, p, len);
2534            buf[len] = '\0';
2535    
2536     fail_unlock:
2537          orinoco_unlock(priv, &flags);          orinoco_unlock(priv, &flags);
2538    
2539          dev_kfree_skb(skb);          return err;      
   
         TRACE_EXIT(dev->name);  
   
         return 0;  
  fail:  
         TRACE_EXIT(dev->name);  
   
         orinoco_unlock(priv, &flags);  
         return err;  
2540  }  }
2541    
2542  static void  static long orinoco_hw_get_freq(struct orinoco_private *priv)
 orinoco_tx_timeout(struct net_device *dev)  
2543  {  {
2544          struct orinoco_private *priv = (struct orinoco_private *)dev->priv;          
2545          struct net_device_stats *stats = &priv->stats;          hermes_t *hw = &priv->hw;
2546          struct hermes *hw = &priv->hw;          int err = 0;
2547            u16 channel;
2548          printk(KERN_WARNING "%s: Tx timeout! "          long freq = 0;
2549                 "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n",          unsigned long flags;
                dev->name, hermes_read_regn(hw, ALLOCFID),  
                hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT));  
   
         stats->tx_errors++;  
2550    
2551          schedule_work(&priv->reset_work);          err = orinoco_lock(priv, &flags);
2552  }          if (err)
2553                    return err;
2554            
2555            err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, &channel);
2556            if (err)
2557                    goto out;
2558    
2559  static int          /* Intersil firmware 1.3.5 returns 0 when the interface is down */
2560  orinoco_change_mtu(struct net_device *dev, int new_mtu)          if (channel == 0) {
2561  {                  err = -EBUSY;
2562          struct orinoco_private *priv = dev->priv;                  goto out;
2563            }
2564    
2565          if ( (new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU) )          if ( (channel < 1) || (channel > NUM_CHANNELS) ) {
2566                  return -EINVAL;                  printk(KERN_WARNING "%s: Channel out of range (%d)!\n",
2567                           priv->ndev->name, channel);
2568                    err = -EBUSY;
2569                    goto out;
2570    
2571          if ( (new_mtu + ENCAPS_OVERHEAD + IEEE802_11_HLEN) >          }
2572               (priv->nicbuf_size - ETH_HLEN) )          freq = channel_frequency[channel-1] * 100000;
                 return -EINVAL;  
2573    
2574          dev->mtu = new_mtu;   out:
2575            orinoco_unlock(priv, &flags);
2576    
2577          return 0;          if (err > 0)
2578                    err = -EBUSY;
2579            return err ? err : freq;
2580  }  }
2581    
2582  /* FIXME: return int? */  static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
2583  static void                                        int *numrates, s32 *rates, int max)
 __orinoco_set_multicast_list(struct net_device *dev)  
2584  {  {
         struct orinoco_private *priv = dev->priv;  
2585          hermes_t *hw = &priv->hw;          hermes_t *hw = &priv->hw;
2586            struct hermes_idstring list;
2587            unsigned char *p = (unsigned char *)&list.val;
2588          int err = 0;          int err = 0;
2589          int promisc, mc_count;          int num;
2590            int i;
2591          /* The Hermes doesn't seem to have an allmulti mode, so we go          unsigned long flags;
          * into promiscuous mode and let the upper levels deal. */  
         if ( (dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) ||  
              (dev->mc_count > MAX_MULTICAST(priv)) ) {  
                 promisc = 1;  
                 mc_count = 0;  
         } else {  
                 promisc = 0;  
                 mc_count = dev->mc_count;  
         }  
2592    
2593          if (promisc != priv->promiscuous) {          err = orinoco_lock(priv, &flags);
2594                  err = hermes_write_wordrec(hw, USER_BAP,          if (err)
2595                                             HERMES_RID_CNFPROMISCUOUSMODE,                  return err;
                                            promisc);  
                 if (err) {  
                         printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n",  
                                dev->name, err);  
                 } else  
                         priv->promiscuous = promisc;  
         }  
2596    
2597          if (! promisc && (mc_count || priv->mc_count) ) {          err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
2598                  struct dev_mc_list *p = dev->mc_list;                                sizeof(list), NULL, &list);
2599                  hermes_multicast_t mclist;          orinoco_unlock(priv, &flags);
                 int i;  
2600    
2601                  for (i = 0; i < mc_count; i++) {          if (err)
2602                          /* Paranoia: */                  return err;
2603                          if (! p)          
2604                                  BUG(); /* Multicast list shorter than mc_count */          num = le16_to_cpu(list.len);
2605                          if (p->dmi_addrlen != ETH_ALEN)          *numrates = num;
2606                                  BUG(); /* Bad address size in multicast list */          num = min(num, max);
                           
                         memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN);  
                         p = p->next;  
                 }  
                   
                 if (p)  
                         printk(KERN_WARNING "Multicast list is longer than mc_count\n");  
2607    
2608                  err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFGROUPADDRESSES,          for (i = 0; i < num; i++) {
2609                                         HERMES_BYTES_TO_RECLEN(priv->mc_count * ETH_ALEN),                  rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */
                                        &mclist);  
                 if (err)  
                         printk(KERN_ERR "%s: Error %d setting multicast list.\n",  
                                dev->name, err);  
                 else  
                         priv->mc_count = mc_count;  
2610          }          }
2611    
2612          /* Since we can set the promiscuous flag when it wasn't asked          return 0;
            for, make sure the net_device knows about it. */  
         if (priv->promiscuous)  
                 dev->flags |= IFF_PROMISC;  
         else  
                 dev->flags &= ~IFF_PROMISC;  
2613  }  }
2614    
 /********************************************************************/  
 /* Wireless extensions support                                      */  
 /********************************************************************/  
   
2615  static int orinoco_ioctl_getiwrange(struct net_device *dev,  static int orinoco_ioctl_getiwrange(struct net_device *dev,
2616                                      struct iw_point *rrq)                                      struct iw_point *rrq)
2617  {  {
# Line 3299  static int orinoco_ioctl_getrate(struct Line 3270  static int orinoco_ioctl_getrate(struct
3270    
3271          ratemode = priv->bitratemode;          ratemode = priv->bitratemode;
3272    
3273          if ( (ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE) )          BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE));
                 BUG();  
3274    
3275          rrq->value = bitrate_table[ratemode].bitrate * 100000;          rrq->value = bitrate_table[ratemode].bitrate * 100000;
3276          rrq->fixed = ! bitrate_table[ratemode].automatic;          rrq->fixed = ! bitrate_table[ratemode].automatic;
# Line 3697  static int orinoco_ioctl_getspy(struct n Line 3667  static int orinoco_ioctl_getspy(struct n
3667          return 0;          return 0;
3668  }  }
3669    
3670  static int  static int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)  
3671  {  {
3672          struct orinoco_private *priv = dev->priv;          struct orinoco_private *priv = dev->priv;
3673          struct iwreq *wrq = (struct iwreq *)rq;          struct iwreq *wrq = (struct iwreq *)rq;
# Line 4044  orinoco_ioctl(struct net_device *dev, st Line 4013  orinoco_ioctl(struct net_device *dev, st
4013          return err;          return err;
4014  }  }
4015    
4016    /********************************************************************/
4017    /* Debugging                                                        */
4018    /********************************************************************/
4019    
4020    #if 0
4021    static void show_rx_frame(struct orinoco_rxframe_hdr *frame)
4022    {
4023            printk(KERN_DEBUG "RX descriptor:\n");
4024            printk(KERN_DEBUG "  status      = 0x%04x\n", frame->desc.status);
4025            printk(KERN_DEBUG "  time        = 0x%08x\n", frame->desc.time);
4026            printk(KERN_DEBUG "  silence     = 0x%02x\n", frame->desc.silence);
4027            printk(KERN_DEBUG "  signal      = 0x%02x\n", frame->desc.signal);
4028            printk(KERN_DEBUG "  rate        = 0x%02x\n", frame->desc.rate);
4029            printk(KERN_DEBUG "  rxflow      = 0x%02x\n", frame->desc.rxflow);
4030            printk(KERN_DEBUG "  reserved    = 0x%08x\n", frame->desc.reserved);
4031    
4032            printk(KERN_DEBUG "IEEE 802.11 header:\n");
4033            printk(KERN_DEBUG "  frame_ctl   = 0x%04x\n",
4034                   frame->p80211.frame_ctl);
4035            printk(KERN_DEBUG "  duration_id = 0x%04x\n",
4036                   frame->p80211.duration_id);
4037            printk(KERN_DEBUG "  addr1       = %02x:%02x:%02x:%02x:%02x:%02x\n",
4038                   frame->p80211.addr1[0], frame->p80211.addr1[1],
4039                   frame->p80211.addr1[2], frame->p80211.addr1[3],
4040                   frame->p80211.addr1[4], frame->p80211.addr1[5]);
4041            printk(KERN_DEBUG "  addr2       = %02x:%02x:%02x:%02x:%02x:%02x\n",
4042                   frame->p80211.addr2[0], frame->p80211.addr2[1],
4043                   frame->p80211.addr2[2], frame->p80211.addr2[3],
4044                   frame->p80211.addr2[4], frame->p80211.addr2[5]);
4045            printk(KERN_DEBUG "  addr3       = %02x:%02x:%02x:%02x:%02x:%02x\n",
4046                   frame->p80211.addr3[0], frame->p80211.addr3[1],
4047                   frame->p80211.addr3[2], frame->p80211.addr3[3],
4048                   frame->p80211.addr3[4], frame->p80211.addr3[5]);
4049            printk(KERN_DEBUG "  seq_ctl     = 0x%04x\n",
4050                   frame->p80211.seq_ctl);
4051            printk(KERN_DEBUG "  addr4       = %02x:%02x:%02x:%02x:%02x:%02x\n",
4052                   frame->p80211.addr4[0], frame->p80211.addr4[1],
4053                   frame->p80211.addr4[2], frame->p80211.addr4[3],
4054                   frame->p80211.addr4[4], frame->p80211.addr4[5]);
4055            printk(KERN_DEBUG "  data_len    = 0x%04x\n",
4056                   frame->p80211.data_len);
4057    
4058            printk(KERN_DEBUG "IEEE 802.3 header:\n");
4059            printk(KERN_DEBUG "  dest        = %02x:%02x:%02x:%02x:%02x:%02x\n",
4060                   frame->p8023.h_dest[0], frame->p8023.h_dest[1],
4061                   frame->p8023.h_dest[2], frame->p8023.h_dest[3],
4062                   frame->p8023.h_dest[4], frame->p8023.h_dest[5]);
4063            printk(KERN_DEBUG "  src         = %02x:%02x:%02x:%02x:%02x:%02x\n",
4064                   frame->p8023.h_source[0], frame->p8023.h_source[1],
4065                   frame->p8023.h_source[2], frame->p8023.h_source[3],
4066                   frame->p8023.h_source[4], frame->p8023.h_source[5]);
4067            printk(KERN_DEBUG "  len         = 0x%04x\n", frame->p8023.h_proto);
4068    
4069            printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");
4070            printk(KERN_DEBUG "  DSAP        = 0x%02x\n", frame->p8022.dsap);
4071            printk(KERN_DEBUG "  SSAP        = 0x%02x\n", frame->p8022.ssap);
4072            printk(KERN_DEBUG "  ctrl        = 0x%02x\n", frame->p8022.ctrl);
4073            printk(KERN_DEBUG "  OUI         = %02x:%02x:%02x\n",
4074                   frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
4075            printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);
4076    }
4077    #endif /* 0 */
4078    
4079  struct {  struct {
4080          u16 rid;          u16 rid;
4081          char *name;          char *name;
# Line 4227  static int orinoco_debug_dump_recs(struc Line 4259  static int orinoco_debug_dump_recs(struc
4259          return 0;          return 0;
4260  }  }
4261    
 struct net_device *alloc_orinocodev(int sizeof_card,  
                                     int (*hard_reset)(struct orinoco_private *))  
 {  
         struct net_device *dev;  
         struct orinoco_private *priv;  
   
         dev = alloc_etherdev(sizeof(struct orinoco_private) + sizeof_card);  
         priv = (struct orinoco_private *)dev->priv;  
         priv->ndev = dev;  
         if (sizeof_card)  
                 priv->card = (void *)((unsigned long)dev->priv  
                                       + sizeof(struct orinoco_private));  
         else  
                 priv->card = NULL;  
   
         /* Setup / override net_device fields */  
         dev->init = orinoco_init;  
         dev->hard_start_xmit = orinoco_xmit;  
         dev->tx_timeout = orinoco_tx_timeout;  
         dev->watchdog_timeo = HZ; /* 1 second timeout */  
         dev->get_stats = orinoco_get_stats;  
         dev->get_wireless_stats = orinoco_get_wireless_stats;  
         dev->do_ioctl = orinoco_ioctl;  
         dev->change_mtu = orinoco_change_mtu;  
         dev->set_multicast_list = orinoco_set_multicast_list;  
         /* we use the default eth_mac_addr for setting the MAC addr */  
   
         /* Set up default callbacks */  
         dev->open = orinoco_open;  
         dev->stop = orinoco_stop;  
         priv->hard_reset = hard_reset;  
   
         spin_lock_init(&priv->lock);  
         priv->open = 0;  
         priv->hw_unavailable = 1; /* orinoco_init() must clear this  
                                    * before anything else touches the  
                                    * hardware */  
         INIT_WORK(&priv->reset_work, (void (*)(void *))orinoco_reset, dev);  
   
         netif_carrier_off(dev);  
         priv->last_linkstatus = 0xffff;  
   
         return dev;  
   
 }  
   
4262  /********************************************************************/  /********************************************************************/
4263  /* Module initialization                                            */  /* Module initialization                                            */
4264  /********************************************************************/  /********************************************************************/

Legend:
Removed from v.1.12  
changed lines
  Added in v.1.13

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26