via-velocity.c

Go to the documentation of this file.
00001 /**************************************************************************
00002 *    via-velocity.c: Etherboot device driver for the VIA 6120 Gigabit
00003 *    Changes for Etherboot port:
00004 *       Copyright (c) 2006 by Timothy Legge <tlegge@rogers.com>
00005 *
00006 *    This program is free software; you can redistribute it and/or modify
00007 *    it under the terms of the GNU General Public License as published by
00008 *    the Free Software Foundation; either version 2 of the License, or
00009 *    (at your option) any later version.
00010 *
00011 *    This program is distributed in the hope that it will be useful,
00012 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 *    GNU General Public License for more details.
00015 *
00016 *    You should have received a copy of the GNU General Public License
00017 *    along with this program; if not, write to the Free Software
00018 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 *
00020 *    This driver is based on:
00021 *         via-velocity.c: VIA Velocity VT6120, VT6122 Ethernet driver 
00022 *             The changes are (c) Copyright 2004, Red Hat Inc. 
00023 *                <alan@redhat.com>
00024 *             Additional fixes and clean up: Francois Romieu
00025 *
00026 *     Original code:
00027 *         Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
00028 *         All rights reserved.
00029 *             Author: Chuang Liang-Shing, AJ Jiang
00030 * 
00031 *    Linux Driver Version 2.6.15.4
00032 * 
00033 *    REVISION HISTORY:
00034 *    ================
00035 *
00036 *    v1.0       03-06-2006      timlegge        Initial port of Linux driver
00037 *    
00038 *    Indent Options: indent -kr -i8
00039 *************************************************************************/
00040 
00041 #include "etherboot.h"
00042 #include "nic.h"
00043 #include <gpxe/pci.h>
00044 #include <gpxe/ethernet.h>
00045 
00046 #include "via-velocity.h"
00047 
00048 typedef int pci_power_t;
00049 
00050 #define PCI_D0  ((int) 0)
00051 #define PCI_D1  ((int) 1)
00052 #define PCI_D2  ((int) 2)
00053 #define PCI_D3hot       ((int) 3)
00054 #define PCI_D3cold      ((int) 4)
00055 #define PCI_POWER_ERROR ((int) -1)
00056 
00057 
00058 /* Condensed operations for readability. */
00059 #define virt_to_le32desc(addr)  cpu_to_le32(virt_to_bus(addr))
00060 #define le32desc_to_virt(addr)  bus_to_virt(le32_to_cpu(addr))
00061 
00062 //FIXME: Move to pci.c
00063 int pci_set_power_state(struct pci_device *dev, int state);
00064 
00065 /* FIXME: Move BASE to the private structure */
00066 static u32 BASE;
00067 
00068 /* NIC specific static variables go here */
00069 #define VELOCITY_PARAM(N,D) \
00070         static const int N[MAX_UNITS]=OPTION_DEFAULT;
00071 /*        MODULE_PARM(N, "1-" __MODULE_STRING(MAX_UNITS) "i");\
00072         MODULE_PARM_DESC(N, D); */
00073 
00074 VELOCITY_PARAM(RxDescriptors, "Number of receive descriptors");
00075 VELOCITY_PARAM(TxDescriptors, "Number of transmit descriptors");
00076 
00077 
00078 #define VLAN_ID_MIN     0
00079 #define VLAN_ID_MAX     4095
00080 #define VLAN_ID_DEF     0
00081 /* VID_setting[] is used for setting the VID of NIC.
00082    0: default VID.
00083    1-4094: other VIDs.
00084 */
00085 VELOCITY_PARAM(VID_setting, "802.1Q VLAN ID");
00086 
00087 #define RX_THRESH_MIN   0
00088 #define RX_THRESH_MAX   3
00089 #define RX_THRESH_DEF   0
00090 /* rx_thresh[] is used for controlling the receive fifo threshold.
00091    0: indicate the rxfifo threshold is 128 bytes.
00092    1: indicate the rxfifo threshold is 512 bytes.
00093    2: indicate the rxfifo threshold is 1024 bytes.
00094    3: indicate the rxfifo threshold is store & forward.
00095 */
00096 VELOCITY_PARAM(rx_thresh, "Receive fifo threshold");
00097 
00098 #define DMA_LENGTH_MIN  0
00099 #define DMA_LENGTH_MAX  7
00100 #define DMA_LENGTH_DEF  0
00101 
00102 /* DMA_length[] is used for controlling the DMA length
00103    0: 8 DWORDs
00104    1: 16 DWORDs
00105    2: 32 DWORDs
00106    3: 64 DWORDs
00107    4: 128 DWORDs
00108    5: 256 DWORDs
00109    6: SF(flush till emply)
00110    7: SF(flush till emply)
00111 */
00112 VELOCITY_PARAM(DMA_length, "DMA length");
00113 
00114 #define TAGGING_DEF     0
00115 /* enable_tagging[] is used for enabling 802.1Q VID tagging.
00116    0: disable VID seeting(default).
00117    1: enable VID setting.
00118 */
00119 VELOCITY_PARAM(enable_tagging, "Enable 802.1Q tagging");
00120 
00121 #define IP_ALIG_DEF     0
00122 /* IP_byte_align[] is used for IP header DWORD byte aligned
00123    0: indicate the IP header won't be DWORD byte aligned.(Default) .
00124    1: indicate the IP header will be DWORD byte aligned.
00125       In some enviroment, the IP header should be DWORD byte aligned,
00126       or the packet will be droped when we receive it. (eg: IPVS)
00127 */
00128 VELOCITY_PARAM(IP_byte_align, "Enable IP header dword aligned");
00129 
00130 #define TX_CSUM_DEF     1
00131 /* txcsum_offload[] is used for setting the checksum offload ability of NIC.
00132    (We only support RX checksum offload now)
00133    0: disable csum_offload[checksum offload
00134    1: enable checksum offload. (Default)
00135 */
00136 VELOCITY_PARAM(txcsum_offload, "Enable transmit packet checksum offload");
00137 
00138 #define FLOW_CNTL_DEF   1
00139 #define FLOW_CNTL_MIN   1
00140 #define FLOW_CNTL_MAX   5
00141 
00142 /* flow_control[] is used for setting the flow control ability of NIC.
00143    1: hardware deafult - AUTO (default). Use Hardware default value in ANAR.
00144    2: enable TX flow control.
00145    3: enable RX flow control.
00146    4: enable RX/TX flow control.
00147    5: disable
00148 */
00149 VELOCITY_PARAM(flow_control, "Enable flow control ability");
00150 
00151 #define MED_LNK_DEF 0
00152 #define MED_LNK_MIN 0
00153 #define MED_LNK_MAX 4
00154 /* speed_duplex[] is used for setting the speed and duplex mode of NIC.
00155    0: indicate autonegotiation for both speed and duplex mode
00156    1: indicate 100Mbps half duplex mode
00157    2: indicate 100Mbps full duplex mode
00158    3: indicate 10Mbps half duplex mode
00159    4: indicate 10Mbps full duplex mode
00160 
00161    Note:
00162         if EEPROM have been set to the force mode, this option is ignored
00163             by driver.
00164 */
00165 VELOCITY_PARAM(speed_duplex, "Setting the speed and duplex mode");
00166 
00167 #define VAL_PKT_LEN_DEF     0
00168 /* ValPktLen[] is used for setting the checksum offload ability of NIC.
00169    0: Receive frame with invalid layer 2 length (Default)
00170    1: Drop frame with invalid layer 2 length
00171 */
00172 VELOCITY_PARAM(ValPktLen, "Receiving or Drop invalid 802.3 frame");
00173 
00174 #define WOL_OPT_DEF     0
00175 #define WOL_OPT_MIN     0
00176 #define WOL_OPT_MAX     7
00177 /* wol_opts[] is used for controlling wake on lan behavior.
00178    0: Wake up if recevied a magic packet. (Default)
00179    1: Wake up if link status is on/off.
00180    2: Wake up if recevied an arp packet.
00181    4: Wake up if recevied any unicast packet.
00182    Those value can be sumed up to support more than one option.
00183 */
00184 VELOCITY_PARAM(wol_opts, "Wake On Lan options");
00185 
00186 #define INT_WORKS_DEF   20
00187 #define INT_WORKS_MIN   10
00188 #define INT_WORKS_MAX   64
00189 
00190 VELOCITY_PARAM(int_works, "Number of packets per interrupt services");
00191 
00192 /* The descriptors for this card are required to be aligned on
00193 64 byte boundaries.  As the align attribute does not guarantee alignment
00194 greater than the alignment of the start address (which for Etherboot
00195 is 16 bytes of alignment) it requires some extra steps.  Add 64 to the 
00196 size of the array and the init_ring adjusts the alignment */
00197 
00198 /* Define the TX Descriptor */
00199 static u8 tx_ring[TX_DESC_DEF * sizeof(struct tx_desc) + 64];
00200 
00201 /* Create a static buffer of size PKT_BUF_SZ for each TX Descriptor.  
00202 All descriptors point to a part of this buffer */
00203 static u8 txb[(TX_DESC_DEF * PKT_BUF_SZ) + 64];
00204 
00205 /* Define the RX Descriptor */
00206 static u8 rx_ring[RX_DESC_DEF * sizeof(struct rx_desc) + 64];
00207 
00208 /* Create a static buffer of size PKT_BUF_SZ for each RX Descriptor
00209    All descriptors point to a part of this buffer */
00210 static u8 rxb[(RX_DESC_DEF * PKT_BUF_SZ) + 64];
00211 
00212 static void velocity_init_info(struct pci_device *pdev,
00213                                struct velocity_info *vptr,
00214                                struct velocity_info_tbl *info);
00215 static int velocity_get_pci_info(struct velocity_info *,
00216                                  struct pci_device *pdev);
00217 static int velocity_open(struct nic *nic, struct pci_device *pci);
00218 
00219 static int velocity_soft_reset(struct velocity_info *vptr);
00220 static void velocity_init_cam_filter(struct velocity_info *vptr);
00221 static void mii_init(struct velocity_info *vptr, u32 mii_status);
00222 static u32 velocity_get_opt_media_mode(struct velocity_info *vptr);
00223 static void velocity_print_link_status(struct velocity_info *vptr);
00224 static void safe_disable_mii_autopoll(struct mac_regs *regs);
00225 static void enable_flow_control_ability(struct velocity_info *vptr);
00226 static void enable_mii_autopoll(struct mac_regs *regs);
00227 static int velocity_mii_read(struct mac_regs *, u8 byIdx, u16 * pdata);
00228 static int velocity_mii_write(struct mac_regs *, u8 byMiiAddr, u16 data);
00229 static u32 mii_check_media_mode(struct mac_regs *regs);
00230 static u32 check_connection_type(struct mac_regs *regs);
00231 static int velocity_set_media_mode(struct velocity_info *vptr,
00232                                    u32 mii_status);
00233 
00234 
00235 /*
00236  *      Internal board variants. At the moment we have only one
00237  */
00238 
00239 static struct velocity_info_tbl chip_info_table[] = {
00240         {CHIP_TYPE_VT6110,
00241          "VIA Networking Velocity Family Gigabit Ethernet Adapter", 256, 1,
00242          0x00FFFFFFUL},
00243         {0, NULL, 0, 0, 0}
00244 };
00245 
00246 /**
00247  *      velocity_set_int_opt    -       parser for integer options
00248  *      @opt: pointer to option value
00249  *      @val: value the user requested (or -1 for default)
00250  *      @min: lowest value allowed
00251  *      @max: highest value allowed
00252  *      @def: default value
00253  *      @name: property name
00254  *      @dev: device name
00255  *
00256  *      Set an integer property in the module options. This function does
00257  *      all the verification and checking as well as reporting so that
00258  *      we don't duplicate code for each option.
00259  */
00260 
00261 static void velocity_set_int_opt(int *opt, int val, int min, int max,
00262                                  int def, char *name, const char *devname)
00263 {
00264         if (val == -1) {
00265                 printf("%s: set value of parameter %s to %d\n",
00266                        devname, name, def);
00267                 *opt = def;
00268         } else if (val < min || val > max) {
00269                 printf
00270                     ("%s: the value of parameter %s is invalid, the valid range is (%d-%d)\n",
00271                      devname, name, min, max);
00272                 *opt = def;
00273         } else {
00274                 printf("%s: set value of parameter %s to %d\n",
00275                        devname, name, val);
00276                 *opt = val;
00277         }
00278 }
00279 
00280 /**
00281  *      velocity_set_bool_opt   -       parser for boolean options
00282  *      @opt: pointer to option value
00283  *      @val: value the user requested (or -1 for default)
00284  *      @def: default value (yes/no)
00285  *      @flag: numeric value to set for true.
00286  *      @name: property name
00287  *      @dev: device name
00288  *
00289  *      Set a boolean property in the module options. This function does
00290  *      all the verification and checking as well as reporting so that
00291  *      we don't duplicate code for each option.
00292  */
00293 
00294 static void velocity_set_bool_opt(u32 * opt, int val, int def, u32 flag,
00295                                   char *name, const char *devname)
00296 {
00297         (*opt) &= (~flag);
00298         if (val == -1) {
00299                 printf("%s: set parameter %s to %s\n",
00300                        devname, name, def ? "TRUE" : "FALSE");
00301                 *opt |= (def ? flag : 0);
00302         } else if (val < 0 || val > 1) {
00303                 printf
00304                     ("%s: the value of parameter %s is invalid, the valid range is (0-1)\n",
00305                      devname, name);
00306                 *opt |= (def ? flag : 0);
00307         } else {
00308                 printf("%s: set parameter %s to %s\n",
00309                        devname, name, val ? "TRUE" : "FALSE");
00310                 *opt |= (val ? flag : 0);
00311         }
00312 }
00313 
00314 /**
00315  *      velocity_get_options    -       set options on device
00316  *      @opts: option structure for the device
00317  *      @index: index of option to use in module options array
00318  *      @devname: device name
00319  *
00320  *      Turn the module and command options into a single structure
00321  *      for the current device
00322  */
00323 
00324 static void velocity_get_options(struct velocity_opt *opts, int index,
00325                                  const char *devname)
00326 {
00327 
00328         /* FIXME Do the options need to be configurable */
00329         velocity_set_int_opt(&opts->rx_thresh, -1, RX_THRESH_MIN,
00330                              RX_THRESH_MAX, RX_THRESH_DEF, "rx_thresh",
00331                              devname);
00332         velocity_set_int_opt(&opts->DMA_length, DMA_length[index],
00333                              DMA_LENGTH_MIN, DMA_LENGTH_MAX,
00334                              DMA_LENGTH_DEF, "DMA_length", devname);
00335         velocity_set_int_opt(&opts->numrx, RxDescriptors[index],
00336                              RX_DESC_MIN, RX_DESC_MAX, RX_DESC_DEF,
00337                              "RxDescriptors", devname);
00338         velocity_set_int_opt(&opts->numtx, TxDescriptors[index],
00339                              TX_DESC_MIN, TX_DESC_MAX, TX_DESC_DEF,
00340                              "TxDescriptors", devname);
00341         velocity_set_int_opt(&opts->vid, VID_setting[index], VLAN_ID_MIN,
00342                              VLAN_ID_MAX, VLAN_ID_DEF, "VID_setting",
00343                              devname);
00344         velocity_set_bool_opt(&opts->flags, enable_tagging[index],
00345                               TAGGING_DEF, VELOCITY_FLAGS_TAGGING,
00346                               "enable_tagging", devname);
00347         velocity_set_bool_opt(&opts->flags, txcsum_offload[index],
00348                               TX_CSUM_DEF, VELOCITY_FLAGS_TX_CSUM,
00349                               "txcsum_offload", devname);
00350         velocity_set_int_opt(&opts->flow_cntl, flow_control[index],
00351                              FLOW_CNTL_MIN, FLOW_CNTL_MAX, FLOW_CNTL_DEF,
00352                              "flow_control", devname);
00353         velocity_set_bool_opt(&opts->flags, IP_byte_align[index],
00354                               IP_ALIG_DEF, VELOCITY_FLAGS_IP_ALIGN,
00355                               "IP_byte_align", devname);
00356         velocity_set_bool_opt(&opts->flags, ValPktLen[index],
00357                               VAL_PKT_LEN_DEF, VELOCITY_FLAGS_VAL_PKT_LEN,
00358                               "ValPktLen", devname);
00359         velocity_set_int_opt((void *) &opts->spd_dpx, speed_duplex[index],
00360                              MED_LNK_MIN, MED_LNK_MAX, MED_LNK_DEF,
00361                              "Media link mode", devname);
00362         velocity_set_int_opt((int *) &opts->wol_opts, wol_opts[index],
00363                              WOL_OPT_MIN, WOL_OPT_MAX, WOL_OPT_DEF,
00364                              "Wake On Lan options", devname);
00365         velocity_set_int_opt((int *) &opts->int_works, int_works[index],
00366                              INT_WORKS_MIN, INT_WORKS_MAX, INT_WORKS_DEF,
00367                              "Interrupt service works", devname);
00368         opts->numrx = (opts->numrx & ~3);
00369 }
00370 
00371 /**
00372  *      velocity_init_cam_filter        -       initialise CAM
00373  *      @vptr: velocity to program
00374  *
00375  *      Initialize the content addressable memory used for filters. Load
00376  *      appropriately according to the presence of VLAN
00377  */
00378 
00379 static void velocity_init_cam_filter(struct velocity_info *vptr)
00380 {
00381         struct mac_regs *regs = vptr->mac_regs;
00382 
00383         /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */
00384         WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, &regs->MCFG);
00385         WORD_REG_BITS_ON(MCFG_VIDFR, &regs->MCFG);
00386 
00387         /* Disable all CAMs */
00388         memset(vptr->vCAMmask, 0, sizeof(u8) * 8);
00389         memset(vptr->mCAMmask, 0, sizeof(u8) * 8);
00390         mac_set_cam_mask(regs, vptr->vCAMmask, VELOCITY_VLAN_ID_CAM);
00391         mac_set_cam_mask(regs, vptr->mCAMmask, VELOCITY_MULTICAST_CAM);
00392 
00393         /* Enable first VCAM */
00394         if (vptr->flags & VELOCITY_FLAGS_TAGGING) {
00395                 /* If Tagging option is enabled and VLAN ID is not zero, then
00396                    turn on MCFG_RTGOPT also */
00397                 if (vptr->options.vid != 0)
00398                         WORD_REG_BITS_ON(MCFG_RTGOPT, &regs->MCFG);
00399 
00400                 mac_set_cam(regs, 0, (u8 *) & (vptr->options.vid),
00401                             VELOCITY_VLAN_ID_CAM);
00402                 vptr->vCAMmask[0] |= 1;
00403                 mac_set_cam_mask(regs, vptr->vCAMmask,
00404                                  VELOCITY_VLAN_ID_CAM);
00405         } else {
00406                 u16 temp = 0;
00407                 mac_set_cam(regs, 0, (u8 *) & temp, VELOCITY_VLAN_ID_CAM);
00408                 temp = 1;
00409                 mac_set_cam_mask(regs, (u8 *) & temp,
00410                                  VELOCITY_VLAN_ID_CAM);
00411         }
00412 }
00413 
00414 static inline void velocity_give_many_rx_descs(struct velocity_info *vptr)
00415 {
00416         struct mac_regs *regs = vptr->mac_regs;
00417         int avail, dirty, unusable;
00418 
00419         /*
00420          * RD number must be equal to 4X per hardware spec
00421          * (programming guide rev 1.20, p.13)
00422          */
00423         if (vptr->rd_filled < 4)
00424                 return;
00425 
00426         wmb();
00427 
00428         unusable = vptr->rd_filled & 0x0003;
00429         dirty = vptr->rd_dirty - unusable;
00430         for (avail = vptr->rd_filled & 0xfffc; avail; avail--) {
00431                 dirty = (dirty > 0) ? dirty - 1 : vptr->options.numrx - 1;
00432 //              printf("return dirty: %d\n", dirty);
00433                 vptr->rd_ring[dirty].rdesc0.owner = OWNED_BY_NIC;
00434         }
00435 
00436         writew(vptr->rd_filled & 0xfffc, &regs->RBRDU);
00437         vptr->rd_filled = unusable;
00438 }
00439 
00440 static int velocity_rx_refill(struct velocity_info *vptr)
00441 {
00442         int dirty = vptr->rd_dirty, done = 0, ret = 0;
00443 
00444 //      printf("rx_refill - rd_curr = %d, dirty = %d\n", vptr->rd_curr, dirty);
00445         do {
00446                 struct rx_desc *rd = vptr->rd_ring + dirty;
00447 
00448                 /* Fine for an all zero Rx desc at init time as well */
00449                 if (rd->rdesc0.owner == OWNED_BY_NIC)
00450                         break;
00451 //              printf("rx_refill - after owner %d\n", dirty);
00452 
00453                 rd->inten = 1;
00454                 rd->pa_high = 0;
00455                 rd->rdesc0.len = cpu_to_le32(vptr->rx_buf_sz);;
00456 
00457                 done++;
00458                 dirty = (dirty < vptr->options.numrx - 1) ? dirty + 1 : 0;
00459         } while (dirty != vptr->rd_curr);
00460 
00461         if (done) {
00462 //              printf("\nGive Back Desc\n");
00463                 vptr->rd_dirty = dirty;
00464                 vptr->rd_filled += done;
00465                 velocity_give_many_rx_descs(vptr);
00466         }
00467 
00468         return ret;
00469 }
00470 
00471 extern void hex_dump(const char *data, const unsigned int len);
00472 /**************************************************************************
00473 POLL - Wait for a frame
00474 ***************************************************************************/
00475 static int velocity_poll(struct nic *nic, int retrieve)
00476 {
00477         /* Work out whether or not there's an ethernet packet ready to
00478          * read.  Return 0 if not.
00479          */
00480 
00481         int rd_curr = vptr->rd_curr % RX_DESC_DEF;
00482         struct rx_desc *rd = &(vptr->rd_ring[rd_curr]);
00483 
00484         if (rd->rdesc0.owner == OWNED_BY_NIC)
00485                 return 0;
00486         rmb();
00487 
00488         if ( ! retrieve ) return 1;
00489 
00490         /*
00491          *      Don't drop CE or RL error frame although RXOK is off
00492          */
00493         if ((rd->rdesc0.RSR & RSR_RXOK)
00494             || (!(rd->rdesc0.RSR & RSR_RXOK)
00495                 && (rd->rdesc0.RSR & (RSR_CE | RSR_RL)))) {
00496 
00497                 nic->packetlen = rd->rdesc0.len;
00498                 // ptr->rxb + (rd_curr * PKT_BUF_SZ)
00499                 memcpy(nic->packet, bus_to_virt(rd->pa_low),
00500                        nic->packetlen - 4);
00501 
00502                 vptr->rd_curr++;
00503                 vptr->rd_curr = vptr->rd_curr % RX_DESC_DEF;
00504                 velocity_rx_refill(vptr);
00505                 return 1;       /* Remove this line once this method is implemented */
00506         }
00507         return 0;
00508 }
00509 
00510 #define TX_TIMEOUT  (1000);
00511 /**************************************************************************
00512 TRANSMIT - Transmit a frame
00513 ***************************************************************************/
00514 static void velocity_transmit(struct nic *nic, const char *dest,        /* Destination */
00515                               unsigned int type,        /* Type */
00516                               unsigned int size,        /* size */
00517                               const char *packet)
00518 {                               /* Packet */
00519         u16 nstype;
00520         u32 to;
00521         u8 *ptxb;
00522         unsigned int pktlen;
00523         struct tx_desc *td_ptr;
00524 
00525         int entry = vptr->td_curr % TX_DESC_DEF;
00526         td_ptr = &(vptr->td_rings[entry]);
00527 
00528         /* point to the current txb incase multiple tx_rings are used */
00529         ptxb = vptr->txb + (entry * PKT_BUF_SZ);
00530         memcpy(ptxb, dest, ETH_ALEN);   /* Destination */
00531         memcpy(ptxb + ETH_ALEN, nic->node_addr, ETH_ALEN);      /* Source */
00532         nstype = htons((u16) type);     /* Type */
00533         memcpy(ptxb + 2 * ETH_ALEN, (u8 *) & nstype, 2);        /* Type */
00534         memcpy(ptxb + ETH_HLEN, packet, size);
00535 
00536         td_ptr->tdesc1.TCPLS = TCPLS_NORMAL;
00537         td_ptr->tdesc1.TCR = TCR0_TIC;
00538         td_ptr->td_buf[0].queue = 0;
00539 
00540         size += ETH_HLEN;
00541         while (size < ETH_ZLEN) /* pad to min length */
00542                 ptxb[size++] = '\0';
00543 
00544         if (size < ETH_ZLEN) {
00545 //              printf("Padd that packet\n");
00546                 pktlen = ETH_ZLEN;
00547 //                memcpy(ptxb, skb->data, skb->len);
00548                 memset(ptxb + size, 0, ETH_ZLEN - size);
00549 
00550                 vptr->td_rings[entry].tdesc0.pktsize = pktlen;
00551                 vptr->td_rings[entry].td_buf[0].pa_low = virt_to_bus(ptxb);
00552                 vptr->td_rings[entry].td_buf[0].pa_high &=
00553                     cpu_to_le32(0xffff0000UL);
00554                 vptr->td_rings[entry].td_buf[0].bufsize =
00555                     vptr->td_rings[entry].tdesc0.pktsize;
00556                 vptr->td_rings[entry].tdesc1.CMDZ = 2;
00557         } else {
00558 //              printf("Correct size packet\n");
00559                 td_ptr->tdesc0.pktsize = size;
00560                 td_ptr->td_buf[0].pa_low = virt_to_bus(ptxb);
00561                 td_ptr->td_buf[0].pa_high = 0;
00562                 td_ptr->td_buf[0].bufsize = td_ptr->tdesc0.pktsize;
00563 //                tdinfo->nskb_dma = 1;
00564                 td_ptr->tdesc1.CMDZ = 2;
00565         }
00566 
00567         if (vptr->flags & VELOCITY_FLAGS_TAGGING) {
00568                 td_ptr->tdesc1.pqinf.VID = (vptr->options.vid & 0xfff);
00569                 td_ptr->tdesc1.pqinf.priority = 0;
00570                 td_ptr->tdesc1.pqinf.CFI = 0;
00571                 td_ptr->tdesc1.TCR |= TCR0_VETAG;
00572         }
00573 
00574         vptr->td_curr = (entry + 1);
00575 
00576         {
00577 
00578                 int prev = entry - 1;
00579 
00580                 if (prev < 0)
00581                         prev = TX_DESC_DEF - 1;
00582                 td_ptr->tdesc0.owner |= OWNED_BY_NIC;
00583                 td_ptr = &(vptr->td_rings[prev]);
00584                 td_ptr->td_buf[0].queue = 1;
00585                 mac_tx_queue_wake(vptr->mac_regs, 0);
00586 
00587         }
00588 
00589         to = currticks() + TX_TIMEOUT;
00590         while ((td_ptr->tdesc0.owner & OWNED_BY_NIC) && (currticks() < to));    /* wait */
00591 
00592         if (currticks() >= to) {
00593                 printf("TX Time Out");
00594         }
00595 
00596 }
00597 
00598 /**************************************************************************
00599 DISABLE - Turn off ethernet interface
00600 ***************************************************************************/
00601 static void velocity_disable(struct nic *nic __unused)
00602 {
00603         /* put the card in its initial state */
00604         /* This function serves 3 purposes.
00605          * This disables DMA and interrupts so we don't receive
00606          *  unexpected packets or interrupts from the card after
00607          *  etherboot has finished. 
00608          * This frees resources so etherboot may use
00609          *  this driver on another interface
00610          * This allows etherboot to reinitialize the interface
00611          *  if something is something goes wrong.
00612          */
00613         struct mac_regs *regs = vptr->mac_regs;
00614         mac_disable_int(regs);
00615         writel(CR0_STOP, &regs->CR0Set);
00616         writew(0xFFFF, &regs->TDCSRClr);
00617         writeb(0xFF, &regs->RDCSRClr);
00618         safe_disable_mii_autopoll(regs);
00619         mac_clear_isr(regs);
00620 
00621         /* Power down the chip */
00622 //      pci_set_power_state(vptr->pdev, PCI_D3hot);
00623 
00624         vptr->flags &= (~VELOCITY_FLAGS_OPENED);
00625 }
00626 
00627 /**************************************************************************
00628 IRQ - handle interrupts
00629 ***************************************************************************/
00630 static void velocity_irq(struct nic *nic __unused, irq_action_t action)
00631 {
00632         /* This routine is somewhat optional.  Etherboot itself
00633          * doesn't use interrupts, but they are required under some
00634          * circumstances when we're acting as a PXE stack.
00635          *
00636          * If you don't implement this routine, the only effect will
00637          * be that your driver cannot be used via Etherboot's UNDI
00638          * API.  This won't affect programs that use only the UDP
00639          * portion of the PXE API, such as pxelinux.
00640          */
00641 
00642         switch (action) {
00643         case DISABLE:
00644         case ENABLE:
00645                 /* Set receive interrupt enabled/disabled state */
00646                 /*
00647                    outb ( action == ENABLE ? IntrMaskEnabled : IntrMaskDisabled,
00648                    nic->ioaddr + IntrMaskRegister );
00649                  */
00650                 break;
00651         case FORCE:
00652                 /* Force NIC to generate a receive interrupt */
00653                 /*
00654                    outb ( ForceInterrupt, nic->ioaddr + IntrForceRegister );
00655                  */
00656                 break;
00657         }
00658 }
00659 
00660 static struct nic_operations velocity_operations = {
00661         .connect        = dummy_connect,
00662         .poll           = velocity_poll,
00663         .transmit       = velocity_transmit,
00664         .irq            = velocity_irq,
00665 };
00666 
00667 /**************************************************************************
00668 PROBE - Look for an adapter, this routine's visible to the outside
00669 ***************************************************************************/
00670 static int velocity_probe( struct nic *nic, struct pci_device *pci)
00671 {
00672         int ret, i;
00673         struct mac_regs *regs;
00674 
00675         printf("via-velocity.c: Found %s Vendor=0x%hX Device=0x%hX\n",
00676                pci->driver_name, pci->vendor, pci->device);
00677 
00678         /* point to private storage */
00679         vptr = &vptx;
00680         info = chip_info_table;
00681 
00682         velocity_init_info(pci, vptr, info);
00683 
00684 //FIXME: pci_enable_device(pci);
00685 //FIXME: pci_set_power_state(pci, PCI_D0);
00686 
00687         ret = velocity_get_pci_info(vptr, pci);
00688         if (ret < 0) {
00689                 printf("Failed to find PCI device.\n");
00690                 return 0;
00691         }
00692 
00693         regs = ioremap(vptr->memaddr, vptr->io_size);
00694         if (regs == NULL) {
00695                 printf("Unable to remap io\n");
00696                 return 0;
00697         }
00698 
00699         vptr->mac_regs = regs;
00700 
00701         BASE = vptr->ioaddr;
00702 
00703         printf("Chip ID: %hX\n", vptr->chip_id);
00704 
00705         for (i = 0; i < 6; i++)
00706                 nic->node_addr[i] = readb(&regs->PAR[i]);
00707 
00708         DBG ( "%s: %s at ioaddr %#hX\n", pci->driver_name, eth_ntoa ( nic->node_addr ),
00709               (unsigned int) BASE );
00710 
00711         velocity_get_options(&vptr->options, 0, pci->driver_name);
00712 
00713         /* 
00714          *      Mask out the options cannot be set to the chip
00715          */
00716         vptr->options.flags &= 0x00FFFFFFUL;    //info->flags = 0x00FFFFFFUL;
00717 
00718         /*
00719          *      Enable the chip specified capbilities
00720          */
00721 
00722         vptr->flags =
00723             vptr->options.
00724             flags | (0x00FFFFFFUL /*info->flags */  & 0xFF000000UL);
00725 
00726         vptr->wol_opts = vptr->options.wol_opts;
00727         vptr->flags |= VELOCITY_FLAGS_WOL_ENABLED;
00728 
00729         vptr->phy_id = MII_GET_PHY_ID(vptr->mac_regs);
00730 
00731         if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) {
00732                 printf("features missing\n");
00733         }
00734 
00735         /* and leave the chip powered down */
00736 // FIXME:       pci_set_power_state(pci, PCI_D3hot);
00737 
00738         check_connection_type(vptr->mac_regs);
00739         velocity_open(nic, pci);
00740 
00741         /* store NIC parameters */
00742         nic->nic_op = &velocity_operations;
00743         return 1;
00744 }
00745 
00746 //#define IORESOURCE_IO              0x00000100      /* Resource type */
00747 
00748 /**
00749  *      velocity_init_info      -       init private data
00750  *      @pdev: PCI device
00751  *      @vptr: Velocity info
00752  *      @info: Board type
00753  *
00754  *      Set up the initial velocity_info struct for the device that has been
00755  *      discovered.
00756  */
00757 
00758 static void velocity_init_info(struct pci_device *pdev,
00759                                struct velocity_info *vptr,
00760                                struct velocity_info_tbl *info)
00761 {
00762         memset(vptr, 0, sizeof(struct velocity_info));
00763 
00764         vptr->pdev = pdev;
00765         vptr->chip_id = info->chip_id;
00766         vptr->io_size = info->io_size;
00767         vptr->num_txq = info->txqueue;
00768         vptr->multicast_limit = MCAM_SIZE;
00769 
00770         printf
00771             ("chip_id: 0x%hX, io_size: %d, num_txq %d, multicast_limit: %d\n",
00772              vptr->chip_id, (unsigned int) vptr->io_size, vptr->num_txq,
00773              vptr->multicast_limit);
00774         printf("Name: %s\n", info->name);
00775 
00776 //      spin_lock_init(&vptr->lock);
00777 //      INIT_LIST_HEAD(&vptr->list);
00778 }
00779 
00780 /**
00781  *      velocity_get_pci_info   -       retrieve PCI info for device
00782  *      @vptr: velocity device
00783  *      @pdev: PCI device it matches
00784  *
00785  *      Retrieve the PCI configuration space data that interests us from
00786  *      the kernel PCI layer
00787  */
00788 
00789 #define IORESOURCE_IO   0x00000100      /* Resource type */
00790 #define IORESOURCE_PREFETCH        0x00001000   /* No side effects */
00791 
00792 #define IORESOURCE_MEM             0x00000200
00793 #define BAR_0           0
00794 #define BAR_1           1
00795 #define BAR_5           5
00796 #define  PCI_BASE_ADDRESS_SPACE 0x01    /* 0 = memory, 1 = I/O */
00797 #define  PCI_BASE_ADDRESS_SPACE_IO 0x01
00798 #define  PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
00799 #define  PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
00800 #define  PCI_BASE_ADDRESS_MEM_TYPE_32   0x00    /* 32 bit address */
00801 #define  PCI_BASE_ADDRESS_MEM_TYPE_1M   0x02    /* Below 1M [obsolete] */
00802 #define  PCI_BASE_ADDRESS_MEM_TYPE_64   0x04    /* 64 bit address */
00803 #define  PCI_BASE_ADDRESS_MEM_PREFETCH  0x08    /* prefetchable? */
00804 //#define  PCI_BASE_ADDRESS_MEM_MASK      (~0x0fUL)
00805 // #define  PCI_BASE_ADDRESS_IO_MASK       (~0x03UL)
00806 
00807 unsigned long pci_resource_flags(struct pci_device *pdev, unsigned int bar)
00808 {
00809         uint32_t l, sz;
00810         unsigned long flags = 0;
00811 
00812         pci_read_config_dword(pdev, bar, &l);
00813         pci_write_config_dword(pdev, bar, ~0);
00814         pci_read_config_dword(pdev, bar, &sz);
00815         pci_write_config_dword(pdev, bar, l);
00816 
00817         if (!sz || sz == 0xffffffff)
00818                 printf("Weird size\n");
00819         if (l == 0xffffffff)
00820                 l = 0;
00821         if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) {
00822                 /*    sz = pci_size(l, sz, PCI_BASE_ADDRESS_MEM_MASK);
00823                    if (!sz)
00824                    continue;
00825                    res->start = l & PCI_BASE_ADDRESS_MEM_MASK;
00826                  */ flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK;
00827                 printf("Memory Resource\n");
00828         } else {
00829                 //            sz = pci_size(l, sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff);
00830                 ///         if (!sz)
00831                 ///              continue;
00832 //              res->start = l & PCI_BASE_ADDRESS_IO_MASK;
00833                 flags |= l & ~PCI_BASE_ADDRESS_IO_MASK;
00834                 printf("I/O Resource\n");
00835         }
00836         if (flags & PCI_BASE_ADDRESS_SPACE_IO) {
00837                 printf("Why is it here\n");
00838                 flags |= IORESOURCE_IO;
00839         } else {
00840                 printf("here\n");
00841 //flags &= ~IORESOURCE_IO;
00842         }
00843 
00844 
00845         if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH)
00846                 flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH;
00847 
00848 
00849         return flags;
00850 }
00851 static int velocity_get_pci_info(struct velocity_info *vptr,
00852                                  struct pci_device *pdev)
00853 {
00854         if (pci_read_config_byte(pdev, PCI_REVISION_ID, &vptr->rev_id) < 0) {
00855                 printf("DEBUG: pci_read_config_byte failed\n");
00856                 return -1;
00857         }
00858 
00859         adjust_pci_device(pdev);
00860 
00861         vptr->ioaddr = pci_bar_start(pdev, PCI_BASE_ADDRESS_0);
00862         vptr->memaddr = pci_bar_start(pdev, PCI_BASE_ADDRESS_1);
00863 
00864         printf("Looking for I/O Resource - Found:");
00865         if (!
00866             (pci_resource_flags(pdev, PCI_BASE_ADDRESS_0) & IORESOURCE_IO))
00867         {
00868                 printf
00869                     ("DEBUG: region #0 is not an I/O resource, aborting.\n");
00870                 return -1;
00871         }
00872 
00873         printf("Looking for Memory Resource - Found:");
00874         if ((pci_resource_flags(pdev, PCI_BASE_ADDRESS_1) & IORESOURCE_IO)) {
00875                 printf("DEBUG: region #1 is an I/O resource, aborting.\n");
00876                 return -1;
00877         }
00878 
00879         if (pci_bar_size(pdev, PCI_BASE_ADDRESS_1) < 256) {
00880                 printf("DEBUG: region #1 is too small.\n");
00881                 return -1;
00882         }
00883         vptr->pdev = pdev;
00884 
00885         return 0;
00886 }
00887 
00888 /**
00889  *      velocity_print_link_status      -       link status reporting
00890  *      @vptr: velocity to report on
00891  *
00892  *      Turn the link status of the velocity card into a kernel log
00893  *      description of the new link state, detailing speed and duplex
00894  *      status
00895  */
00896 
00897 static void velocity_print_link_status(struct velocity_info *vptr)
00898 {
00899 
00900         if (vptr->mii_status & VELOCITY_LINK_FAIL) {
00901                 printf("failed to detect cable link\n");
00902         } else if (vptr->options.spd_dpx == SPD_DPX_AUTO) {
00903                 printf("Link autonegation");
00904 
00905                 if (vptr->mii_status & VELOCITY_SPEED_1000)
00906                         printf(" speed 1000M bps");
00907                 else if (vptr->mii_status & VELOCITY_SPEED_100)
00908                         printf(" speed 100M bps");
00909                 else
00910                         printf(" speed 10M bps");
00911 
00912                 if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
00913                         printf(" full duplex\n");
00914                 else
00915                         printf(" half duplex\n");
00916         } else {
00917                 printf("Link forced");
00918                 switch (vptr->options.spd_dpx) {
00919                 case SPD_DPX_100_HALF:
00920                         printf(" speed 100M bps half duplex\n");
00921                         break;
00922                 case SPD_DPX_100_FULL:
00923                         printf(" speed 100M bps full duplex\n");
00924                         break;
00925                 case SPD_DPX_10_HALF:
00926                         printf(" speed 10M bps half duplex\n");
00927                         break;
00928                 case SPD_DPX_10_FULL:
00929                         printf(" speed 10M bps full duplex\n");
00930                         break;
00931                 default:
00932                         break;
00933                 }
00934         }
00935 }
00936 
00937 /**
00938  *      velocity_rx_reset       -       handle a receive reset
00939  *      @vptr: velocity we are resetting
00940  *
00941  *      Reset the ownership and status for the receive ring side.
00942  *      Hand all the receive queue to the NIC.
00943  */
00944 
00945 static void velocity_rx_reset(struct velocity_info *vptr)
00946 {
00947 
00948         struct mac_regs *regs = vptr->mac_regs;
00949         int i;
00950 
00951 //ptr->rd_dirty = vptr->rd_filled = vptr->rd_curr = 0;
00952 
00953         /*
00954          *      Init state, all RD entries belong to the NIC
00955          */
00956         for (i = 0; i < vptr->options.numrx; ++i)
00957                 vptr->rd_ring[i].rdesc0.owner = OWNED_BY_NIC;
00958 
00959         writew(RX_DESC_DEF, &regs->RBRDU);
00960         writel(virt_to_le32desc(vptr->rd_ring), &regs->RDBaseLo);
00961         writew(0, &regs->RDIdx);
00962         writew(RX_DESC_DEF - 1, &regs->RDCSize);
00963 }
00964 
00965 /**
00966  *      velocity_init_registers -       initialise MAC registers
00967  *      @vptr: velocity to init
00968  *      @type: type of initialisation (hot or cold)
00969  *
00970  *      Initialise the MAC on a reset or on first set up on the
00971  *      hardware.
00972  */
00973 
00974 static void velocity_init_registers(struct nic *nic,
00975                                     struct velocity_info *vptr,
00976                                     enum velocity_init_type type)
00977 {
00978         struct mac_regs *regs = vptr->mac_regs;
00979         int i, mii_status;
00980 
00981         mac_wol_reset(regs);
00982 
00983         switch (type) {
00984         case VELOCITY_INIT_RESET:
00985         case VELOCITY_INIT_WOL:
00986 
00987 //netif_stop_queue(vptr->dev);
00988 
00989                 /*
00990                  *      Reset RX to prevent RX pointer not on the 4X location
00991                  */
00992                 velocity_rx_reset(vptr);
00993                 mac_rx_queue_run(regs);
00994                 mac_rx_queue_wake(regs);
00995 
00996                 mii_status = velocity_get_opt_media_mode(vptr);
00997 
00998                 if (velocity_set_media_mode(vptr, mii_status) !=
00999                     VELOCITY_LINK_CHANGE) {
01000                         velocity_print_link_status(vptr);
01001                         if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
01002                                 printf("Link Failed\n");
01003 //                              netif_wake_queue(vptr->dev);
01004                 }
01005 
01006                 enable_flow_control_ability(vptr);
01007 
01008                 mac_clear_isr(regs);
01009                 writel(CR0_STOP, &regs->CR0Clr);
01010                 //writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT), 
01011                 writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT),
01012                        &regs->CR0Set);
01013                 break;
01014 
01015         case VELOCITY_INIT_COLD:
01016         default:
01017                 /*
01018                  *      Do reset
01019                  */
01020                 velocity_soft_reset(vptr);
01021                 mdelay(5);
01022 
01023                 mac_eeprom_reload(regs);
01024                 for (i = 0; i < 6; i++) {
01025                         writeb(nic->node_addr[i], &(regs->PAR[i]));
01026                 }
01027                 /*
01028                  *      clear Pre_ACPI bit.
01029                  */
01030                 BYTE_REG_BITS_OFF(CFGA_PACPI, &(regs->CFGA));
01031                 mac_set_rx_thresh(regs, vptr->options.rx_thresh);
01032                 mac_set_dma_length(regs, vptr->options.DMA_length);
01033 
01034                 writeb(WOLCFG_SAM | WOLCFG_SAB, &regs->WOLCFGSet);
01035                 /*
01036                  *      Back off algorithm use original IEEE standard
01037                  */
01038                 BYTE_REG_BITS_SET(CFGB_OFSET,
01039                                   (CFGB_CRANDOM | CFGB_CAP | CFGB_MBA |
01040                                    CFGB_BAKOPT), &regs->CFGB);
01041 
01042                 /*
01043                  *      Init CAM filter
01044                  */
01045                 velocity_init_cam_filter(vptr);
01046 
01047                 /*
01048                  *      Set packet filter: Receive directed and broadcast address
01049                  */
01050 //FIXME Multicast               velocity_set_multi(nic);
01051 
01052                 /*
01053                  *      Enable MII auto-polling
01054                  */
01055                 enable_mii_autopoll(regs);
01056 
01057                 vptr->int_mask = INT_MASK_DEF;
01058 
01059                 writel(virt_to_le32desc(vptr->rd_ring), &regs->RDBaseLo);
01060                 writew(vptr->options.numrx - 1, &regs->RDCSize);
01061                 mac_rx_queue_run(regs);
01062                 mac_rx_queue_wake(regs);
01063 
01064                 writew(vptr->options.numtx - 1, &regs->TDCSize);
01065 
01066 //              for (i = 0; i < vptr->num_txq; i++) {
01067                 writel(virt_to_le32desc(vptr->td_rings),
01068                        &(regs->TDBaseLo[0]));
01069                 mac_tx_queue_run(regs, 0);
01070 //              }
01071 
01072                 init_flow_control_register(vptr);
01073 
01074                 writel(CR0_STOP, &regs->CR0Clr);
01075                 writel((CR0_DPOLL | CR0_TXON | CR0_RXON | CR0_STRT),
01076                        &regs->CR0Set);
01077 
01078                 mii_status = velocity_get_opt_media_mode(vptr);
01079 //              netif_stop_queue(vptr->dev);
01080 
01081                 mii_init(vptr, mii_status);
01082 
01083                 if (velocity_set_media_mode(vptr, mii_status) !=
01084                     VELOCITY_LINK_CHANGE) {
01085                         velocity_print_link_status(vptr);
01086                         if (!(vptr->mii_status & VELOCITY_LINK_FAIL))
01087                                 printf("Link Faaailll\n");
01088 //                              netif_wake_queue(vptr->dev);
01089                 }
01090 
01091                 enable_flow_control_ability(vptr);
01092                 mac_hw_mibs_init(regs);
01093                 mac_write_int_mask(vptr->int_mask, regs);
01094                 mac_clear_isr(regs);
01095 
01096 
01097         }
01098         velocity_print_link_status(vptr);
01099 }
01100 
01101 /**
01102  *      velocity_soft_reset     -       soft reset
01103  *      @vptr: velocity to reset
01104  *
01105  *      Kick off a soft reset of the velocity adapter and then poll
01106  *      until the reset sequence has completed before returning.
01107  */
01108 
01109 static int velocity_soft_reset(struct velocity_info *vptr)
01110 {
01111         struct mac_regs *regs = vptr->mac_regs;
01112         unsigned int i = 0;
01113 
01114         writel(CR0_SFRST, &regs->CR0Set);
01115 
01116         for (i = 0; i < W_MAX_TIMEOUT; i++) {
01117                 udelay(5);
01118                 if (!DWORD_REG_BITS_IS_ON(CR0_SFRST, &regs->CR0Set))
01119                         break;
01120         }
01121 
01122         if (i == W_MAX_TIMEOUT) {
01123                 writel(CR0_FORSRST, &regs->CR0Set);
01124                 /* FIXME: PCI POSTING */
01125                 /* delay 2ms */
01126                 mdelay(2);
01127         }
01128         return 0;
01129 }
01130 
01131 /**
01132  *      velocity_init_rings     -       set up DMA rings
01133  *      @vptr: Velocity to set up
01134  *
01135  *      Allocate PCI mapped DMA rings for the receive and transmit layer
01136  *      to use.
01137  */
01138 
01139 static int velocity_init_rings(struct velocity_info *vptr)
01140 {
01141 
01142         int idx;
01143 
01144         vptr->rd_curr = 0;
01145         vptr->td_curr = 0;
01146         memset(vptr->td_rings, 0, TX_DESC_DEF * sizeof(struct tx_desc));
01147         memset(vptr->rd_ring, 0, RX_DESC_DEF * sizeof(struct rx_desc));
01148 //      memset(vptr->tx_buffs, 0, TX_DESC_DEF * PKT_BUF_SZ);
01149 
01150 
01151         for (idx = 0; idx < RX_DESC_DEF; idx++) {
01152                 vptr->rd_ring[idx].rdesc0.RSR = 0;
01153                 vptr->rd_ring[idx].rdesc0.len = 0;
01154                 vptr->rd_ring[idx].rdesc0.reserved = 0;
01155                 vptr->rd_ring[idx].rdesc0.owner = 0;
01156                 vptr->rd_ring[idx].len = cpu_to_le32(vptr->rx_buf_sz);
01157                 vptr->rd_ring[idx].inten = 1;
01158                 vptr->rd_ring[idx].pa_low =
01159                     virt_to_bus(vptr->rxb + (RX_DESC_DEF * idx));
01160                 vptr->rd_ring[idx].pa_high = 0;
01161                 vptr->rd_ring[idx].rdesc0.owner = OWNED_BY_NIC;
01162         }
01163 
01164 /*      for (i = 0; idx < TX_DESC_DEF; idx++ ) {
01165                 vptr->td_rings[idx].tdesc1.TCPLS = TCPLS_NORMAL;
01166                 vptr->td_rings[idx].tdesc1.TCR = TCR0_TIC;
01167                 vptr->td_rings[idx].td_buf[0].queue = 0;
01168                 vptr->td_rings[idx].tdesc0.owner = ~OWNED_BY_NIC;
01169                 vptr->td_rings[idx].tdesc0.pktsize = 0;
01170                 vptr->td_rings[idx].td_buf[0].pa_low = cpu_to_le32(virt_to_bus(vptr->txb + (idx * PKT_BUF_SZ)));
01171                 vptr->td_rings[idx].td_buf[0].pa_high = 0;
01172                 vptr->td_rings[idx].td_buf[0].bufsize = 0;
01173                 vptr->td_rings[idx].tdesc1.CMDZ = 2;
01174         }
01175 */
01176         return 0;
01177 }
01178 
01179 /**
01180  *      velocity_open           -       interface activation callback
01181  *      @dev: network layer device to open
01182  *
01183  *      Called when the network layer brings the interface up. Returns
01184  *      a negative posix error code on failure, or zero on success.
01185  *
01186  *      All the ring allocation and set up is done on open for this
01187  *      adapter to minimise memory usage when inactive
01188  */
01189 
01190 #define PCI_BYTE_REG_BITS_ON(x,i,p) do{\
01191     u8 byReg;\
01192     pci_read_config_byte((p), (i), &(byReg));\
01193     (byReg) |= (x);\
01194     pci_write_config_byte((p), (i), (byReg));\
01195 } while (0)
01196 
01197 //
01198 // Registers in the PCI configuration space
01199 //
01200 #define PCI_REG_COMMAND         0x04    //
01201 #define PCI_REG_MODE0           0x60    //
01202 #define PCI_REG_MODE1           0x61    //
01203 #define PCI_REG_MODE2           0x62    //
01204 #define PCI_REG_MODE3           0x63    //
01205 #define PCI_REG_DELAY_TIMER     0x64    //
01206 
01207 // Bits in the (MODE2, 0x62) register
01208 //
01209 #define MODE2_PCEROPT       0x80        // take PCI bus ERror as a fatal and shutdown from software control
01210 #define MODE2_TXQ16         0x40        // TX write-back Queue control. 0->32 entries available in Tx write-back queue, 1->16 entries
01211 #define MODE2_TXPOST        0x08        // (Not support in VT3119)
01212 #define MODE2_AUTOOPT       0x04        // (VT3119 GHCI without such behavior)
01213 #define MODE2_MODE10T       0x02        // used to control tx Threshold for 10M case
01214 #define MODE2_TCPLSOPT      0x01        // TCP large send field update disable, hardware will not update related fields, leave it to software.
01215 
01216 //
01217 // Bits in the MODE3 register
01218 //
01219 #define MODE3_MIION         0x04        // MII symbol codine error detect enable ??
01220 
01221 // Bits in the (COMMAND, 0x04) register
01222 #define COMMAND_BUSM        0x04
01223 #define COMMAND_WAIT        0x80
01224 static int velocity_open(struct nic *nic, struct pci_device *pci __unused)
01225 {
01226         int ret;
01227 
01228         u8 diff;
01229         u32 TxPhyAddr, RxPhyAddr;
01230         u32 TxBufPhyAddr, RxBufPhyAddr;
01231         vptr->TxDescArrays = tx_ring;
01232         if (vptr->TxDescArrays == 0)
01233                 printf("Allot Error");
01234 
01235         /* Tx Descriptor needs 64 bytes alignment; */
01236         TxPhyAddr = virt_to_bus(vptr->TxDescArrays);
01237         printf("Unaligned Address : %X\n", TxPhyAddr);
01238         diff = 64 - (TxPhyAddr - ((TxPhyAddr >> 6) << 6));
01239         TxPhyAddr += diff;
01240         vptr->td_rings = (struct tx_desc *) (vptr->TxDescArrays + diff);
01241 
01242         printf("Aligned Address: %lX\n", virt_to_bus(vptr->td_rings));
01243         vptr->tx_buffs = txb;
01244         /* Rx Buffer needs 64 bytes alignment; */
01245         TxBufPhyAddr = virt_to_bus(vptr->tx_buffs);
01246         diff = 64 - (TxBufPhyAddr - ((TxBufPhyAddr >> 6) << 6));
01247         TxBufPhyAddr += diff;
01248         vptr->txb = (unsigned char *) (vptr->tx_buffs + diff);
01249 
01250         vptr->RxDescArrays = rx_ring;
01251         /* Rx Descriptor needs 64 bytes alignment; */
01252         RxPhyAddr = virt_to_bus(vptr->RxDescArrays);
01253         diff = 64 - (RxPhyAddr - ((RxPhyAddr >> 6) << 6));
01254         RxPhyAddr += diff;
01255         vptr->rd_ring = (struct rx_desc *) (vptr->RxDescArrays + diff);
01256 
01257         vptr->rx_buffs = rxb;
01258         /* Rx Buffer needs 64 bytes alignment; */
01259         RxBufPhyAddr = virt_to_bus(vptr->rx_buffs);
01260         diff = 64 - (RxBufPhyAddr - ((RxBufPhyAddr >> 6) << 6));
01261         RxBufPhyAddr += diff;
01262         vptr->rxb = (unsigned char *) (vptr->rx_buffs + diff);
01263 
01264         if (vptr->RxDescArrays == NULL || vptr->RxDescArrays == NULL) {
01265                 printf("Allocate tx_ring or rd_ring failed\n");
01266                 return 0;
01267         }
01268 
01269         vptr->rx_buf_sz = PKT_BUF_SZ;
01270 /*
01271     // turn this on to avoid retry forever
01272     PCI_BYTE_REG_BITS_ON(MODE2_PCEROPT, PCI_REG_MODE2, pci);
01273     // for some legacy BIOS and OS don't open BusM
01274     // bit in PCI configuration space. So, turn it on.
01275     PCI_BYTE_REG_BITS_ON(COMMAND_BUSM, PCI_REG_COMMAND, pci);
01276     // turn this on to detect MII coding error
01277     PCI_BYTE_REG_BITS_ON(MODE3_MIION, PCI_REG_MODE3, pci);
01278  */
01279         ret = velocity_init_rings(vptr);
01280 
01281         /* Ensure chip is running */
01282 //FIXME:        pci_set_power_state(vptr->pdev, PCI_D0);
01283 
01284         velocity_init_registers(nic, vptr, VELOCITY_INIT_COLD);
01285         mac_write_int_mask(0, vptr->mac_regs);
01286 //      _int(vptr->mac_regs);
01287         //mac_enable_int(vptr->mac_regs);
01288 
01289         vptr->flags |= VELOCITY_FLAGS_OPENED;
01290         return 1;
01291 
01292 }
01293 
01294 /*
01295  * MII access , media link mode setting functions
01296  */
01297 
01298 
01299 /**
01300  *      mii_init        -       set up MII
01301  *      @vptr: velocity adapter
01302  *      @mii_status:  links tatus
01303  *
01304  *      Set up the PHY for the current link state.
01305  */
01306 
01307 static void mii_init(struct velocity_info *vptr, u32 mii_status __unused)
01308 {
01309         u16 BMCR;
01310 
01311         switch (PHYID_GET_PHY_ID(vptr->phy_id)) {
01312         case PHYID_CICADA_CS8201:
01313                 /*
01314                  *      Reset to hardware default
01315                  */
01316                 MII_REG_BITS_OFF((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR,
01317                                  vptr->mac_regs);
01318                 /*
01319                  *      Turn on ECHODIS bit in NWay-forced full mode and turn it
01320                  *      off it in NWay-forced half mode for NWay-forced v.s. 
01321                  *      legacy-forced issue.
01322                  */
01323                 if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
01324                         MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR,
01325                                         vptr->mac_regs);
01326                 else
01327                         MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR,
01328                                          vptr->mac_regs);
01329                 /*
01330                  *      Turn on Link/Activity LED enable bit for CIS8201
01331                  */
01332                 MII_REG_BITS_ON(PLED_LALBE, MII_REG_PLED, vptr->mac_regs);
01333                 break;
01334         case PHYID_VT3216_32BIT:
01335         case PHYID_VT3216_64BIT:
01336                 /*
01337                  *      Reset to hardware default
01338                  */
01339                 MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR,
01340                                 vptr->mac_regs);
01341                 /*
01342                  *      Turn on ECHODIS bit in NWay-forced full mode and turn it
01343                  *      off it in NWay-forced half mode for NWay-forced v.s. 
01344                  *      legacy-forced issue
01345                  */
01346                 if (vptr->mii_status & VELOCITY_DUPLEX_FULL)
01347                         MII_REG_BITS_ON(TCSR_ECHODIS, MII_REG_TCSR,
01348                                         vptr->mac_regs);
01349                 else
01350                         MII_REG_BITS_OFF(TCSR_ECHODIS, MII_REG_TCSR,
01351                                          vptr->mac_regs);
01352                 break;
01353 
01354         case PHYID_MARVELL_1000:
01355         case PHYID_MARVELL_1000S:
01356                 /*
01357                  *      Assert CRS on Transmit 
01358                  */
01359                 MII_REG_BITS_ON(PSCR_ACRSTX, MII_REG_PSCR, vptr->mac_regs);
01360                 /*
01361                  *      Reset to hardware default 
01362                  */
01363                 MII_REG_BITS_ON((ANAR_ASMDIR | ANAR_PAUSE), MII_REG_ANAR,
01364                                 vptr->mac_regs);
01365                 break;
01366         default:
01367                 ;
01368         }
01369         velocity_mii_read(vptr->mac_regs, MII_REG_BMCR, &BMCR);
01370         if (BMCR & BMCR_ISO) {
01371                 BMCR &= ~BMCR_ISO;
01372                 velocity_mii_write(vptr->mac_regs, MII_REG_BMCR, BMCR);
01373         }
01374 }
01375 
01376 /**
01377  *      safe_disable_mii_autopoll       -       autopoll off
01378  *      @regs: velocity registers
01379  *
01380  *      Turn off the autopoll and wait for it to disable on the chip
01381  */
01382 
01383 static void safe_disable_mii_autopoll(struct mac_regs *regs)
01384 {
01385         u16 ww;
01386 
01387         /*  turn off MAUTO */
01388         writeb(0, &regs->MIICR);
01389         for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
01390                 udelay(1);
01391                 if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
01392                         break;
01393         }
01394 }
01395 
01396 /**
01397  *      enable_mii_autopoll     -       turn on autopolling
01398  *      @regs: velocity registers
01399  *
01400  *      Enable the MII link status autopoll feature on the Velocity
01401  *      hardware. Wait for it to enable.
01402  */
01403 
01404 static void enable_mii_autopoll(struct mac_regs *regs)
01405 {
01406         unsigned int ii;
01407 
01408         writeb(0, &(regs->MIICR));
01409         writeb(MIIADR_SWMPL, &regs->MIIADR);
01410 
01411         for (ii = 0; ii < W_MAX_TIMEOUT; ii++) {
01412                 udelay(1);
01413                 if (BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
01414                         break;
01415         }
01416 
01417         writeb(MIICR_MAUTO, &regs->MIICR);
01418 
01419         for (ii = 0; ii < W_MAX_TIMEOUT; ii++) {
01420                 udelay(1);
01421                 if (!BYTE_REG_BITS_IS_ON(MIISR_MIDLE, &regs->MIISR))
01422                         break;
01423         }
01424 
01425 }
01426 
01427 /**
01428  *      velocity_mii_read       -       read MII data
01429  *      @regs: velocity registers
01430  *      @index: MII register index
01431  *      @data: buffer for received data
01432  *
01433  *      Perform a single read of an MII 16bit register. Returns zero
01434  *      on success or -ETIMEDOUT if the PHY did not respond.
01435  */
01436 
01437 static int velocity_mii_read(struct mac_regs *regs, u8 index, u16 * data)
01438 {
01439         u16 ww;
01440 
01441         /*
01442          *      Disable MIICR_MAUTO, so that mii addr can be set normally
01443          */
01444         safe_disable_mii_autopoll(regs);
01445 
01446         writeb(index, &regs->MIIADR);
01447 
01448         BYTE_REG_BITS_ON(MIICR_RCMD, &regs->MIICR);
01449 
01450         for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
01451                 if (!(readb(&regs->MIICR) & MIICR_RCMD))
01452                         break;
01453         }
01454 
01455         *data = readw(&regs->MIIDATA);
01456 
01457         enable_mii_autopoll(regs);
01458         if (ww == W_MAX_TIMEOUT)
01459                 return -1;
01460         return 0;
01461 }
01462 
01463 /**
01464  *      velocity_mii_write      -       write MII data
01465  *      @regs: velocity registers
01466  *      @index: MII register index
01467  *      @data: 16bit data for the MII register
01468  *
01469  *      Perform a single write to an MII 16bit register. Returns zero
01470  *      on success or -ETIMEDOUT if the PHY did not respond.
01471  */
01472 
01473 static int velocity_mii_write(struct mac_regs *regs, u8 mii_addr, u16 data)
01474 {
01475         u16 ww;
01476 
01477         /*
01478          *      Disable MIICR_MAUTO, so that mii addr can be set normally
01479          */
01480         safe_disable_mii_autopoll(regs);
01481 
01482         /* MII reg offset */
01483         writeb(mii_addr, &regs->MIIADR);
01484         /* set MII data */
01485         writew(data, &regs->MIIDATA);
01486 
01487         /* turn on MIICR_WCMD */
01488         BYTE_REG_BITS_ON(MIICR_WCMD, &regs->MIICR);
01489 
01490         /* W_MAX_TIMEOUT is the timeout period */
01491         for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
01492                 udelay(5);
01493                 if (!(readb(&regs->MIICR) & MIICR_WCMD))
01494                         break;
01495         }
01496         enable_mii_autopoll(regs);
01497 
01498         if (ww == W_MAX_TIMEOUT)
01499                 return -1;
01500         return 0;
01501 }
01502 
01503 /**
01504  *      velocity_get_opt_media_mode     -       get media selection
01505  *      @vptr: velocity adapter
01506  *
01507  *      Get the media mode stored in EEPROM or module options and load
01508  *      mii_status accordingly. The requested link state information
01509  *      is also returned.
01510  */
01511 
01512 static u32 velocity_get_opt_media_mode(struct velocity_info *vptr)
01513 {
01514         u32 status = 0;
01515 
01516         switch (vptr->options.spd_dpx) {
01517         case SPD_DPX_AUTO:
01518                 status = VELOCITY_AUTONEG_ENABLE;
01519                 break;
01520         case SPD_DPX_100_FULL:
01521                 status = VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL;
01522                 break;
01523         case SPD_DPX_10_FULL:
01524                 status = VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL;
01525                 break;
01526         case SPD_DPX_100_HALF:
01527                 status = VELOCITY_SPEED_100;
01528                 break;
01529         case SPD_DPX_10_HALF:
01530                 status = VELOCITY_SPEED_10;
01531                 break;
01532         }
01533         vptr->mii_status = status;
01534         return status;
01535 }
01536 
01537 /**
01538  *      mii_set_auto_on         -       autonegotiate on
01539  *      @vptr: velocity
01540  *
01541  *      Enable autonegotation on this interface
01542  */
01543 
01544 static void mii_set_auto_on(struct velocity_info *vptr)
01545 {
01546         if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs))
01547                 MII_REG_BITS_ON(BMCR_REAUTO, MII_REG_BMCR, vptr->mac_regs);
01548         else
01549                 MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs);
01550 }
01551 
01552 
01553 /*
01554 static void mii_set_auto_off(struct velocity_info * vptr)
01555 {
01556     MII_REG_BITS_OFF(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs);
01557 }
01558 */
01559 
01560 /**
01561  *      set_mii_flow_control    -       flow control setup
01562  *      @vptr: velocity interface
01563  *
01564  *      Set up the flow control on this interface according to
01565  *      the supplied user/eeprom options.
01566  */
01567 
01568 static void set_mii_flow_control(struct velocity_info *vptr)
01569 {
01570         /*Enable or Disable PAUSE in ANAR */
01571         switch (vptr->options.flow_cntl) {
01572         case FLOW_CNTL_TX:
01573                 MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
01574                 MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
01575                 break;
01576 
01577         case FLOW_CNTL_RX:
01578                 MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
01579                 MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
01580                 break;
01581 
01582         case FLOW_CNTL_TX_RX:
01583                 MII_REG_BITS_ON(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
01584                 MII_REG_BITS_ON(ANAR_ASMDIR, MII_REG_ANAR, vptr->mac_regs);
01585                 break;
01586 
01587         case FLOW_CNTL_DISABLE:
01588                 MII_REG_BITS_OFF(ANAR_PAUSE, MII_REG_ANAR, vptr->mac_regs);
01589                 MII_REG_BITS_OFF(ANAR_ASMDIR, MII_REG_ANAR,
01590                                  vptr->mac_regs);
01591                 break;
01592         default:
01593                 break;
01594         }
01595 }
01596 
01597 /**
01598  *      velocity_set_media_mode         -       set media mode
01599  *      @mii_status: old MII link state
01600  *
01601  *      Check the media link state and configure the flow control
01602  *      PHY and also velocity hardware setup accordingly. In particular
01603  *      we need to set up CD polling and frame bursting.
01604  */
01605 
01606 static int velocity_set_media_mode(struct velocity_info *vptr,
01607                                    u32 mii_status)
01608 {
01609         u32 curr_status;
01610         struct mac_regs *regs = vptr->mac_regs;
01611 
01612         vptr->mii_status = mii_check_media_mode(vptr->mac_regs);
01613         curr_status = vptr->mii_status & (~VELOCITY_LINK_FAIL);
01614 
01615         /* Set mii link status */
01616         set_mii_flow_control(vptr);
01617 
01618         /*
01619            Check if new status is consisent with current status
01620            if (((mii_status & curr_status) & VELOCITY_AUTONEG_ENABLE)
01621            || (mii_status==curr_status)) {
01622            vptr->mii_status=mii_check_media_mode(vptr->mac_regs);
01623            vptr->mii_status=check_connection_type(vptr->mac_regs);
01624            printf(MSG_LEVEL_INFO, "Velocity link no change\n");
01625            return 0;
01626            }
01627          */
01628 
01629         if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201) {
01630                 MII_REG_BITS_ON(AUXCR_MDPPS, MII_REG_AUXCR,
01631                                 vptr->mac_regs);
01632         }
01633 
01634         /*
01635          *      If connection type is AUTO
01636          */
01637         if (mii_status & VELOCITY_AUTONEG_ENABLE) {
01638                 printf("Velocity is AUTO mode\n");
01639                 /* clear force MAC mode bit */
01640                 BYTE_REG_BITS_OFF(CHIPGCR_FCMODE, &regs->CHIPGCR);
01641                 /* set duplex mode of MAC according to duplex mode of MII */
01642                 MII_REG_BITS_ON(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10,
01643                                 MII_REG_ANAR, vptr->mac_regs);
01644                 MII_REG_BITS_ON(G1000CR_1000FD | G1000CR_1000,
01645                                 MII_REG_G1000CR, vptr->mac_regs);
01646                 MII_REG_BITS_ON(BMCR_SPEED1G, MII_REG_BMCR,
01647                                 vptr->mac_regs);
01648 
01649                 /* enable AUTO-NEGO mode */
01650                 mii_set_auto_on(vptr);
01651         } else {
01652                 u16 ANAR;
01653                 u8 CHIPGCR;
01654 
01655                 /*
01656                  * 1. if it's 3119, disable frame bursting in halfduplex mode
01657                  *    and enable it in fullduplex mode
01658                  * 2. set correct MII/GMII and half/full duplex mode in CHIPGCR
01659                  * 3. only enable CD heart beat counter in 10HD mode
01660                  */
01661 
01662                 /* set force MAC mode bit */
01663                 BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
01664 
01665                 CHIPGCR = readb(&regs->CHIPGCR);
01666                 CHIPGCR &= ~CHIPGCR_FCGMII;
01667 
01668                 if (mii_status & VELOCITY_DUPLEX_FULL) {
01669                         CHIPGCR |= CHIPGCR_FCFDX;
01670                         writeb(CHIPGCR, &regs->CHIPGCR);
01671                         printf
01672                             ("DEBUG: set Velocity to forced full mode\n");
01673                         if (vptr->rev_id < REV_ID_VT3216_A0)
01674                                 BYTE_REG_BITS_OFF(TCR_TB2BDIS, &regs->TCR);
01675                 } else {
01676                         CHIPGCR &= ~CHIPGCR_FCFDX;
01677                         printf
01678                             ("DEBUG: set Velocity to forced half mode\n");
01679                         writeb(CHIPGCR, &regs->CHIPGCR);
01680                         if (vptr->rev_id < REV_ID_VT3216_A0)
01681                                 BYTE_REG_BITS_ON(TCR_TB2BDIS, &regs->TCR);
01682                 }
01683 
01684                 MII_REG_BITS_OFF(G1000CR_1000FD | G1000CR_1000,
01685                                  MII_REG_G1000CR, vptr->mac_regs);
01686 
01687                 if (!(mii_status & VELOCITY_DUPLEX_FULL)
01688                     && (mii_status & VELOCITY_SPEED_10)) {
01689                         BYTE_REG_BITS_OFF(TESTCFG_HBDIS, &regs->TESTCFG);
01690                 } else {
01691                         BYTE_REG_BITS_ON(TESTCFG_HBDIS, &regs->TESTCFG);
01692                 }
01693                 /* MII_REG_BITS_OFF(BMCR_SPEED1G, MII_REG_BMCR, vptr->mac_regs); */
01694                 velocity_mii_read(vptr->mac_regs, MII_REG_ANAR, &ANAR);
01695                 ANAR &= (~(ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10));
01696                 if (mii_status & VELOCITY_SPEED_100) {
01697                         if (mii_status & VELOCITY_DUPLEX_FULL)
01698                                 ANAR |= ANAR_TXFD;
01699                         else
01700                                 ANAR |= ANAR_TX;
01701                 } else {
01702                         if (mii_status & VELOCITY_DUPLEX_FULL)
01703                                 ANAR |= ANAR_10FD;
01704                         else
01705                                 ANAR |= ANAR_10;
01706                 }
01707                 velocity_mii_write(vptr->mac_regs, MII_REG_ANAR, ANAR);
01708                 /* enable AUTO-NEGO mode */
01709                 mii_set_auto_on(vptr);
01710                 /* MII_REG_BITS_ON(BMCR_AUTO, MII_REG_BMCR, vptr->mac_regs); */
01711         }
01712         /* vptr->mii_status=mii_check_media_mode(vptr->mac_regs); */
01713         /* vptr->mii_status=check_connection_type(vptr->mac_regs); */
01714         return VELOCITY_LINK_CHANGE;
01715 }
01716 
01717 /**
01718  *      mii_check_media_mode    -       check media state
01719  *      @regs: velocity registers
01720  *
01721  *      Check the current MII status and determine the link status
01722  *      accordingly
01723  */
01724 
01725 static u32 mii_check_media_mode(struct mac_regs *regs)
01726 {
01727         u32 status = 0;
01728         u16 ANAR;
01729 
01730         if (!MII_REG_BITS_IS_ON(BMSR_LNK, MII_REG_BMSR, regs))
01731                 status |= VELOCITY_LINK_FAIL;
01732 
01733         if (MII_REG_BITS_IS_ON(G1000CR_1000FD, MII_REG_G1000CR, regs))
01734                 status |= VELOCITY_SPEED_1000 | VELOCITY_DUPLEX_FULL;
01735         else if (MII_REG_BITS_IS_ON(G1000CR_1000, MII_REG_G1000CR, regs))
01736                 status |= (VELOCITY_SPEED_1000);
01737         else {
01738                 velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
01739                 if (ANAR & ANAR_TXFD)
01740                         status |=
01741                             (VELOCITY_SPEED_100 | VELOCITY_DUPLEX_FULL);
01742                 else if (ANAR & ANAR_TX)
01743                         status |= VELOCITY_SPEED_100;
01744                 else if (ANAR & ANAR_10FD)
01745                         status |=
01746                             (VELOCITY_SPEED_10 | VELOCITY_DUPLEX_FULL);
01747                 else
01748                         status |= (VELOCITY_SPEED_10);
01749         }
01750 
01751         if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) {
01752                 velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
01753                 if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10))
01754                     == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) {
01755                         if (MII_REG_BITS_IS_ON
01756                             (G1000CR_1000 | G1000CR_1000FD,
01757                              MII_REG_G1000CR, regs))
01758                                 status |= VELOCITY_AUTONEG_ENABLE;
01759                 }
01760         }
01761 
01762         return status;
01763 }
01764 
01765 static u32 check_connection_type(struct mac_regs *regs)
01766 {
01767         u32 status = 0;
01768         u8 PHYSR0;
01769         u16 ANAR;
01770         PHYSR0 = readb(&regs->PHYSR0);
01771 
01772         /*
01773            if (!(PHYSR0 & PHYSR0_LINKGD))
01774            status|=VELOCITY_LINK_FAIL;
01775          */
01776 
01777         if (PHYSR0 & PHYSR0_FDPX)
01778                 status |= VELOCITY_DUPLEX_FULL;
01779 
01780         if (PHYSR0 & PHYSR0_SPDG)
01781                 status |= VELOCITY_SPEED_1000;
01782         if (PHYSR0 & PHYSR0_SPD10)
01783                 status |= VELOCITY_SPEED_10;
01784         else
01785                 status |= VELOCITY_SPEED_100;
01786 
01787         if (MII_REG_BITS_IS_ON(BMCR_AUTO, MII_REG_BMCR, regs)) {
01788                 velocity_mii_read(regs, MII_REG_ANAR, &ANAR);
01789                 if ((ANAR & (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10))
01790                     == (ANAR_TXFD | ANAR_TX | ANAR_10FD | ANAR_10)) {
01791                         if (MII_REG_BITS_IS_ON
01792                             (G1000CR_1000 | G1000CR_1000FD,
01793                              MII_REG_G1000CR, regs))
01794                                 status |= VELOCITY_AUTONEG_ENABLE;
01795                 }
01796         }
01797 
01798         return status;
01799 }
01800 
01801 /**
01802  *      enable_flow_control_ability     -       flow control
01803  *      @vptr: veloity to configure
01804  *
01805  *      Set up flow control according to the flow control options
01806  *      determined by the eeprom/configuration.
01807  */
01808 
01809 static void enable_flow_control_ability(struct velocity_info *vptr)
01810 {
01811 
01812         struct mac_regs *regs = vptr->mac_regs;
01813 
01814         switch (vptr->options.flow_cntl) {
01815 
01816         case FLOW_CNTL_DEFAULT:
01817                 if (BYTE_REG_BITS_IS_ON(PHYSR0_RXFLC, &regs->PHYSR0))
01818                         writel(CR0_FDXRFCEN, &regs->CR0Set);
01819                 else
01820                         writel(CR0_FDXRFCEN, &regs->CR0Clr);
01821 
01822                 if (BYTE_REG_BITS_IS_ON(PHYSR0_TXFLC, &regs->PHYSR0))
01823                         writel(CR0_FDXTFCEN, &regs->CR0Set);
01824                 else
01825                         writel(CR0_FDXTFCEN, &regs->CR0Clr);
01826                 break;
01827 
01828         case FLOW_CNTL_TX:
01829                 writel(CR0_FDXTFCEN, &regs->CR0Set);
01830                 writel(CR0_FDXRFCEN, &regs->CR0Clr);
01831                 break;
01832 
01833         case FLOW_CNTL_RX:
01834                 writel(CR0_FDXRFCEN, &regs->CR0Set);
01835                 writel(CR0_FDXTFCEN, &regs->CR0Clr);
01836                 break;
01837 
01838         case FLOW_CNTL_TX_RX:
01839                 writel(CR0_FDXTFCEN, &regs->CR0Set);
01840                 writel(CR0_FDXRFCEN, &regs->CR0Set);
01841                 break;
01842 
01843         case FLOW_CNTL_DISABLE:
01844                 writel(CR0_FDXRFCEN, &regs->CR0Clr);
01845                 writel(CR0_FDXTFCEN, &regs->CR0Clr);
01846                 break;
01847 
01848         default:
01849                 break;
01850         }
01851 
01852 }
01853 
01854 /* FIXME: Move to pci.c */
01855 /**
01856  * pci_set_power_state - Set the power state of a PCI device
01857  * @dev: PCI device to be suspended
01858  * @state: Power state we're entering
01859  *
01860  * Transition a device to a new power state, using the Power Management 
01861  * Capabilities in the device's config space.
01862  *
01863  * RETURN VALUE: 
01864  * -EINVAL if trying to enter a lower state than we're already in.
01865  * 0 if we're already in the requested state.
01866  * -EIO if device does not support PCI PM.
01867  * 0 if we can successfully change the power state.
01868  */
01869 
01870 int pci_set_power_state(struct pci_device *dev, int state)
01871 {
01872         int pm;
01873         u16 pmcsr;
01874         int current_state = 0;
01875 
01876         /* bound the state we're entering */
01877         if (state > 3)
01878                 state = 3;
01879 
01880         /* Validate current state:
01881          * Can enter D0 from any state, but if we can only go deeper 
01882          * to sleep if we're already in a low power state
01883          */
01884         if (state > 0 && current_state > state)
01885                 return -1;
01886         else if (current_state == state)
01887                 return 0;       /* we're already there */
01888 
01889         /* find PCI PM capability in list */
01890         pm = pci_find_capability(dev, PCI_CAP_ID_PM);
01891 
01892         /* abort if the device doesn't support PM capabilities */
01893         if (!pm)
01894                 return -2;
01895 
01896         /* check if this device supports the desired state */
01897         if (state == 1 || state == 2) {
01898                 u16 pmc;
01899                 pci_read_config_word(dev, pm + PCI_PM_PMC, &pmc);
01900                 if (state == 1 && !(pmc & PCI_PM_CAP_D1))
01901                         return -2;
01902                 else if (state == 2 && !(pmc & PCI_PM_CAP_D2))
01903                         return -2;
01904         }
01905 
01906         /* If we're in D3, force entire word to 0.
01907          * This doesn't affect PME_Status, disables PME_En, and
01908          * sets PowerState to 0.
01909          */
01910         if (current_state >= 3)
01911                 pmcsr = 0;
01912         else {
01913                 pci_read_config_word(dev, pm + PCI_PM_CTRL, &pmcsr);
01914                 pmcsr &= ~PCI_PM_CTRL_STATE_MASK;
01915                 pmcsr |= state;
01916         }
01917 
01918         /* enter specified state */
01919         pci_write_config_word(dev, pm + PCI_PM_CTRL, pmcsr);
01920 
01921         /* Mandatory power management transition delays */
01922         /* see PCI PM 1.1 5.6.1 table 18 */
01923         if (state == 3 || current_state == 3)
01924                 mdelay(10);
01925         else if (state == 2 || current_state == 2)
01926                 udelay(200);
01927         current_state = state;
01928 
01929         return 0;
01930 }
01931 
01932 static struct pci_device_id velocity_nics[] = {
01933         PCI_ROM(0x1106, 0x3119, "via-velocity", "VIA Networking Velocity Family Gigabit Ethernet Adapter", 0),
01934 };
01935 
01936 PCI_DRIVER ( velocity_driver, velocity_nics, PCI_NO_CLASS );
01937 
01938 DRIVER ( "VIA-VELOCITY/PCI", nic_driver, pci_driver, velocity_driver,
01939          velocity_probe, velocity_disable );

Generated on Tue Apr 6 20:01:05 2010 for gPXE by  doxygen 1.5.7.1