1 /*******************************************************************************
2  * Agere Systems Inc.
3  * Wireless device driver for Linux (wlags49).
4  *
5  * Copyright (c) 1998-2003 Agere Systems Inc.
6  * All rights reserved.
7  *   http://www.agere.com
8  *
9  * Initially developed by TriplePoint, Inc.
10  *   http://www.triplepoint.com
11  *
12  *------------------------------------------------------------------------------
13  *
14  *   This file contains handler functions registered with the net_device
15  *   structure.
16  *
17  *------------------------------------------------------------------------------
18  *
19  * SOFTWARE LICENSE
20  *
21  * This software is provided subject to the following terms and conditions,
22  * which you should read carefully before using the software.  Using this
23  * software indicates your acceptance of these terms and conditions.  If you do
24  * not agree with these terms and conditions, do not use the software.
25  *
26  * Copyright � 2003 Agere Systems Inc.
27  * All rights reserved.
28  *
29  * Redistribution and use in source or binary forms, with or without
30  * modifications, are permitted provided that the following conditions are met:
31  *
32  * . Redistributions of source code must retain the above copyright notice, this
33  *    list of conditions and the following Disclaimer as comments in the code as
34  *    well as in the documentation and/or other materials provided with the
35  *    distribution.
36  *
37  * . Redistributions in binary form must reproduce the above copyright notice,
38  *    this list of conditions and the following Disclaimer in the documentation
39  *    and/or other materials provided with the distribution.
40  *
41  * . Neither the name of Agere Systems Inc. nor the names of the contributors
42  *    may be used to endorse or promote products derived from this software
43  *    without specific prior written permission.
44  *
45  * Disclaimer
46  *
47  * THIS SOFTWARE IS PROVIDED �AS IS� AND ANY EXPRESS OR IMPLIED WARRANTIES,
48  * INCLUDING, BUT NOT LIMITED TO, INFRINGEMENT AND THE IMPLIED WARRANTIES OF
49  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  ANY
50  * USE, MODIFICATION OR DISTRIBUTION OF THIS SOFTWARE IS SOLELY AT THE USERS OWN
51  * RISK. IN NO EVENT SHALL AGERE SYSTEMS INC. OR CONTRIBUTORS BE LIABLE FOR ANY
52  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
54  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
55  * ON ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, CONTRACT, STRICT
56  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
57  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
58  * DAMAGE.
59  *
60  ******************************************************************************/
61 
62 /*******************************************************************************
63  * include files
64  ******************************************************************************/
65 #include <wl_version.h>
66 
67 #include <linux/module.h>
68 #include <linux/slab.h>
69 #include <linux/types.h>
70 #include <linux/kernel.h>
71 // #include <linux/sched.h>
72 // #include <linux/ptrace.h>
73 // #include <linux/slab.h>
74 // #include <linux/ctype.h>
75 // #include <linux/string.h>
76 //#include <linux/timer.h>
77 // #include <linux/interrupt.h>
78 // #include <linux/in.h>
79 // #include <linux/delay.h>
80 // #include <linux/skbuff.h>
81 // #include <asm/io.h>
82 // #include <asm/system.h>
83 // #include <asm/bitops.h>
84 
85 #include <linux/netdevice.h>
86 #include <linux/ethtool.h>
87 #include <linux/etherdevice.h>
88 // #include <linux/skbuff.h>
89 // #include <linux/if_arp.h>
90 // #include <linux/ioport.h>
91 
92 #include <debug.h>
93 
94 #include <hcf.h>
95 #include <dhf.h>
96 // #include <hcfdef.h>
97 
98 #include <wl_if.h>
99 #include <wl_internal.h>
100 #include <wl_util.h>
101 #include <wl_priv.h>
102 #include <wl_main.h>
103 #include <wl_netdev.h>
104 #include <wl_wext.h>
105 
106 #ifdef USE_PROFILE
107 #include <wl_profile.h>
108 #endif  /* USE_PROFILE */
109 
110 #ifdef BUS_PCMCIA
111 #include <wl_cs.h>
112 #endif  /* BUS_PCMCIA */
113 
114 #ifdef BUS_PCI
115 #include <wl_pci.h>
116 #endif  /* BUS_PCI */
117 
118 
119 /*******************************************************************************
120  * global variables
121  ******************************************************************************/
122 #if DBG
123 extern dbg_info_t *DbgInfo;
124 #endif  /* DBG */
125 
126 
127 #if HCF_ENCAP
128 #define MTU_MAX (HCF_MAX_MSG - ETH_HLEN - 8)
129 #else
130 #define MTU_MAX (HCF_MAX_MSG - ETH_HLEN)
131 #endif
132 
133 //static int mtu = MTU_MAX;
134 //MODULE_PARM(mtu, "i");
135 //MODULE_PARM_DESC(mtu, "MTU");
136 
137 /*******************************************************************************
138  * macros
139  ******************************************************************************/
140 #define BLOCK_INPUT(buf, len) \
141     desc->buf_addr = buf; \
142     desc->BUF_SIZE = len; \
143     status = hcf_rcv_msg(&(lp->hcfCtx), desc, 0)
144 
145 #define BLOCK_INPUT_DMA(buf, len) memcpy( buf, desc_next->buf_addr, pktlen )
146 
147 /*******************************************************************************
148  * function prototypes
149  ******************************************************************************/
150 
151 /*******************************************************************************
152  *	wl_init()
153  *******************************************************************************
154  *
155  *  DESCRIPTION:
156  *
157  *      We never need to do anything when a "Wireless" device is "initialized"
158  *  by the net software, because we only register already-found cards.
159  *
160  *  PARAMETERS:
161  *
162  *      dev - a pointer to the device's net_device structure
163  *
164  *  RETURNS:
165  *
166  *      0 on success
167  *      errno value otherwise
168  *
169  ******************************************************************************/
wl_init(struct net_device * dev)170 int wl_init( struct net_device *dev )
171 {
172 //    unsigned long       flags;
173 //    struct wl_private   *lp = wl_priv(dev);
174     /*------------------------------------------------------------------------*/
175 
176     DBG_FUNC( "wl_init" );
177     DBG_ENTER( DbgInfo );
178 
179     DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
180 
181     /* Nothing to do, but grab the spinlock anyway just in case we ever need
182        this routine */
183 //  wl_lock( lp, &flags );
184 //  wl_unlock( lp, &flags );
185 
186     DBG_LEAVE( DbgInfo );
187     return 0;
188 } // wl_init
189 /*============================================================================*/
190 
191 /*******************************************************************************
192  *	wl_config()
193  *******************************************************************************
194  *
195  *  DESCRIPTION:
196  *
197  *      Implement the SIOCSIFMAP interface.
198  *
199  *  PARAMETERS:
200  *
201  *      dev - a pointer to the device's net_device structure
202  *      map - a pointer to the device's ifmap structure
203  *
204  *  RETURNS:
205  *
206  *      0 on success
207  *      errno otherwise
208  *
209  ******************************************************************************/
wl_config(struct net_device * dev,struct ifmap * map)210 int wl_config( struct net_device *dev, struct ifmap *map )
211 {
212     DBG_FUNC( "wl_config" );
213     DBG_ENTER( DbgInfo );
214 
215     DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
216     DBG_PARAM( DbgInfo, "map", "0x%p", map );
217 
218     /* The only thing we care about here is a port change. Since this not needed,
219        ignore the request. */
220     DBG_TRACE( DbgInfo, "%s: %s called.\n", dev->name, __FUNC__ );
221 
222     DBG_LEAVE( DbgInfo );
223     return 0;
224 } // wl_config
225 /*============================================================================*/
226 
227 /*******************************************************************************
228  *	wl_stats()
229  *******************************************************************************
230  *
231  *  DESCRIPTION:
232  *
233  *      Return the current device statistics.
234  *
235  *  PARAMETERS:
236  *
237  *      dev - a pointer to the device's net_device structure
238  *
239  *  RETURNS:
240  *
241  *      a pointer to a net_device_stats structure containing the network
242  *      statistics.
243  *
244  ******************************************************************************/
wl_stats(struct net_device * dev)245 struct net_device_stats *wl_stats( struct net_device *dev )
246 {
247 #ifdef USE_WDS
248     int                         count;
249 #endif  /* USE_WDS */
250     unsigned long               flags;
251     struct net_device_stats     *pStats;
252     struct wl_private           *lp = wl_priv(dev);
253     /*------------------------------------------------------------------------*/
254 
255     //DBG_FUNC( "wl_stats" );
256     //DBG_ENTER( DbgInfo );
257     //DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
258 
259     pStats = NULL;
260 
261     wl_lock( lp, &flags );
262 
263 #ifdef USE_RTS
264     if( lp->useRTS == 1 ) {
265 	wl_unlock( lp, &flags );
266 
267 	//DBG_LEAVE( DbgInfo );
268 	return NULL;
269     }
270 #endif  /* USE_RTS */
271 
272     /* Return the statistics for the appropriate device */
273 #ifdef USE_WDS
274 
275     for( count = 0; count < NUM_WDS_PORTS; count++ ) {
276 	if( dev == lp->wds_port[count].dev ) {
277 	    pStats = &( lp->wds_port[count].stats );
278 	}
279     }
280 
281 #endif  /* USE_WDS */
282 
283     /* If pStats is still NULL, then the device is not a WDS port */
284     if( pStats == NULL ) {
285         pStats = &( lp->stats );
286     }
287 
288     wl_unlock( lp, &flags );
289 
290     //DBG_LEAVE( DbgInfo );
291 
292     return pStats;
293 } // wl_stats
294 /*============================================================================*/
295 
296 /*******************************************************************************
297  *	wl_open()
298  *******************************************************************************
299  *
300  *  DESCRIPTION:
301  *
302  *      Open the device.
303  *
304  *  PARAMETERS:
305  *
306  *      dev - a pointer to the device's net_device structure
307  *
308  *  RETURNS:
309  *
310  *      0 on success
311  *      errno otherwise
312  *
313  ******************************************************************************/
wl_open(struct net_device * dev)314 int wl_open(struct net_device *dev)
315 {
316     int                 status = HCF_SUCCESS;
317     struct wl_private   *lp = wl_priv(dev);
318     unsigned long       flags;
319     /*------------------------------------------------------------------------*/
320 
321     DBG_FUNC( "wl_open" );
322     DBG_ENTER( DbgInfo );
323 
324     wl_lock( lp, &flags );
325 
326 #ifdef USE_RTS
327     if( lp->useRTS == 1 ) {
328 	DBG_TRACE( DbgInfo, "Skipping device open, in RTS mode\n" );
329 	wl_unlock( lp, &flags );
330 	DBG_LEAVE( DbgInfo );
331 	return -EIO;
332     }
333 #endif  /* USE_RTS */
334 
335 #ifdef USE_PROFILE
336     parse_config( dev );
337 #endif
338 
339     if( lp->portState == WVLAN_PORT_STATE_DISABLED ) {
340 	DBG_TRACE( DbgInfo, "Enabling Port 0\n" );
341 	status = wl_enable( lp );
342 
343         if( status != HCF_SUCCESS ) {
344             DBG_TRACE( DbgInfo, "Enable port 0 failed: 0x%x\n", status );
345         }
346     }
347 
348     // Holding the lock too long, make a gap to allow other processes
349     wl_unlock(lp, &flags);
350     wl_lock( lp, &flags );
351 
352     if ( strlen( lp->fw_image_filename ) ) {
353 	DBG_TRACE( DbgInfo, ";???? Kludgy way to force a download\n" );
354 	status = wl_go( lp );
355     } else {
356 	status = wl_apply( lp );
357     }
358 
359     // Holding the lock too long, make a gap to allow other processes
360     wl_unlock(lp, &flags);
361     wl_lock( lp, &flags );
362 
363     if( status != HCF_SUCCESS ) {
364 	// Unsuccessful, try reset of the card to recover
365 	status = wl_reset( dev );
366     }
367 
368     // Holding the lock too long, make a gap to allow other processes
369     wl_unlock(lp, &flags);
370     wl_lock( lp, &flags );
371 
372     if( status == HCF_SUCCESS ) {
373 	netif_carrier_on( dev );
374 	WL_WDS_NETIF_CARRIER_ON( lp );
375 
376 	lp->is_handling_int = WL_HANDLING_INT; // Start handling interrupts
377         wl_act_int_on( lp );
378 
379 	netif_start_queue( dev );
380 	WL_WDS_NETIF_START_QUEUE( lp );
381     } else {
382         wl_hcf_error( dev, status );		/* Report the error */
383         netif_device_detach( dev );		/* Stop the device and queue */
384     }
385 
386     wl_unlock( lp, &flags );
387 
388     DBG_LEAVE( DbgInfo );
389     return status;
390 } // wl_open
391 /*============================================================================*/
392 
393 /*******************************************************************************
394  *	wl_close()
395  *******************************************************************************
396  *
397  *  DESCRIPTION:
398  *
399  *      Close the device.
400  *
401  *  PARAMETERS:
402  *
403  *      dev - a pointer to the device's net_device structure
404  *
405  *  RETURNS:
406  *
407  *      0 on success
408  *      errno otherwise
409  *
410  ******************************************************************************/
wl_close(struct net_device * dev)411 int wl_close( struct net_device *dev )
412 {
413     struct wl_private   *lp = wl_priv(dev);
414     unsigned long   flags;
415     /*------------------------------------------------------------------------*/
416 
417     DBG_FUNC("wl_close");
418     DBG_ENTER(DbgInfo);
419     DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
420 
421     /* Mark the adapter as busy */
422     netif_stop_queue( dev );
423     WL_WDS_NETIF_STOP_QUEUE( lp );
424 
425     netif_carrier_off( dev );
426     WL_WDS_NETIF_CARRIER_OFF( lp );
427 
428     /* Shutdown the adapter:
429             Disable adapter interrupts
430             Stop Tx/Rx
431             Update statistics
432             Set low power mode
433     */
434 
435     wl_lock( lp, &flags );
436 
437     wl_act_int_off( lp );
438     lp->is_handling_int = WL_NOT_HANDLING_INT; // Stop handling interrupts
439 
440 #ifdef USE_RTS
441     if( lp->useRTS == 1 ) {
442 	DBG_TRACE( DbgInfo, "Skipping device close, in RTS mode\n" );
443 	wl_unlock( lp, &flags );
444 	DBG_LEAVE( DbgInfo );
445 	return -EIO;
446     }
447 #endif  /* USE_RTS */
448 
449     /* Disable the ports */
450     wl_disable( lp );
451 
452     wl_unlock( lp, &flags );
453 
454     DBG_LEAVE( DbgInfo );
455     return 0;
456 } // wl_close
457 /*============================================================================*/
458 
wl_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * info)459 static void wl_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
460 {
461     strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1);
462     strncpy(info->version, DRV_VERSION_STR, sizeof(info->version) - 1);
463 //	strncpy(info.fw_version, priv->fw_name,
464 //	sizeof(info.fw_version) - 1);
465 
466     if (dev->dev.parent) {
467     	dev_set_name(dev->dev.parent, "%s", info->bus_info);
468 	//strncpy(info->bus_info, dev->dev.parent->bus_id,
469 	//	sizeof(info->bus_info) - 1);
470     } else {
471 	snprintf(info->bus_info, sizeof(info->bus_info) - 1,
472 		"PCMCIA FIXME");
473 //		    "PCMCIA 0x%lx", priv->hw.iobase);
474     }
475 } // wl_get_drvinfo
476 
477 static struct ethtool_ops wl_ethtool_ops = {
478     .get_drvinfo = wl_get_drvinfo,
479     .get_link = ethtool_op_get_link,
480 };
481 
482 
483 /*******************************************************************************
484  *	wl_ioctl()
485  *******************************************************************************
486  *
487  *  DESCRIPTION:
488  *
489  *      The IOCTL handler for the device.
490  *
491  *  PARAMETERS:
492  *
493  *      dev - a pointer to the device's net_device struct.
494  *      rq  - a pointer to the IOCTL request buffer.
495  *      cmd - the IOCTL command code.
496  *
497  *  RETURNS:
498  *
499  *      0 on success
500  *      errno value otherwise
501  *
502  ******************************************************************************/
wl_ioctl(struct net_device * dev,struct ifreq * rq,int cmd)503 int wl_ioctl( struct net_device *dev, struct ifreq *rq, int cmd )
504 {
505     struct wl_private  *lp = wl_priv(dev);
506     unsigned long           flags;
507     int                     ret = 0;
508     /*------------------------------------------------------------------------*/
509 
510     DBG_FUNC( "wl_ioctl" );
511     DBG_ENTER(DbgInfo);
512     DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
513     DBG_PARAM(DbgInfo, "rq", "0x%p", rq);
514     DBG_PARAM(DbgInfo, "cmd", "0x%04x", cmd);
515 
516     wl_lock( lp, &flags );
517 
518     wl_act_int_off( lp );
519 
520 #ifdef USE_RTS
521     if( lp->useRTS == 1 ) {
522 	/* Handle any RTS IOCTL here */
523 	if( cmd == WL_IOCTL_RTS ) {
524 	    DBG_TRACE( DbgInfo, "IOCTL: WL_IOCTL_RTS\n" );
525 	    ret = wvlan_rts( (struct rtsreq *)rq, dev->base_addr );
526 	} else {
527 	    DBG_TRACE( DbgInfo, "IOCTL not supported in RTS mode: 0x%X\n", cmd );
528 	    ret = -EOPNOTSUPP;
529 	}
530 
531 	goto out_act_int_on_unlock;
532     }
533 #endif  /* USE_RTS */
534 
535     /* Only handle UIL IOCTL requests when the UIL has the system blocked. */
536     if( !(( lp->flags & WVLAN2_UIL_BUSY ) && ( cmd != WVLAN2_IOCTL_UIL ))) {
537 #ifdef USE_UIL
538 	struct uilreq  *urq = (struct uilreq *)rq;
539 #endif /* USE_UIL */
540 
541 	switch( cmd ) {
542 		// ================== Private IOCTLs (up to 16) ==================
543 #ifdef USE_UIL
544 	case WVLAN2_IOCTL_UIL:
545 	     DBG_TRACE( DbgInfo, "IOCTL: WVLAN2_IOCTL_UIL\n" );
546 	     ret = wvlan_uil( urq, lp );
547 	     break;
548 #endif  /* USE_UIL */
549 
550 	default:
551 	     DBG_TRACE(DbgInfo, "IOCTL CODE NOT SUPPORTED: 0x%X\n", cmd );
552 	     ret = -EOPNOTSUPP;
553 	     break;
554 	}
555     } else {
556 	DBG_WARNING( DbgInfo, "DEVICE IS BUSY, CANNOT PROCESS REQUEST\n" );
557 	ret = -EBUSY;
558     }
559 
560 #ifdef USE_RTS
561 out_act_int_on_unlock:
562 #endif  /* USE_RTS */
563     wl_act_int_on( lp );
564 
565     wl_unlock( lp, &flags );
566 
567     DBG_LEAVE( DbgInfo );
568     return ret;
569 } // wl_ioctl
570 /*============================================================================*/
571 
572 #ifdef CONFIG_NET_POLL_CONTROLLER
wl_poll(struct net_device * dev)573 void wl_poll(struct net_device *dev)
574 {
575     struct wl_private *lp = wl_priv(dev);
576     unsigned long flags;
577     struct pt_regs regs;
578 
579     wl_lock( lp, &flags );
580     wl_isr(dev->irq, dev, &regs);
581     wl_unlock( lp, &flags );
582 }
583 #endif
584 
585 /*******************************************************************************
586  *	wl_tx_timeout()
587  *******************************************************************************
588  *
589  *  DESCRIPTION:
590  *
591  *      The handler called when, for some reason, a Tx request is not completed.
592  *
593  *  PARAMETERS:
594  *
595  *      dev - a pointer to the device's net_device struct.
596  *
597  *  RETURNS:
598  *
599  *      N/A
600  *
601  ******************************************************************************/
wl_tx_timeout(struct net_device * dev)602 void wl_tx_timeout( struct net_device *dev )
603 {
604 #ifdef USE_WDS
605     int                     count;
606 #endif  /* USE_WDS */
607     unsigned long           flags;
608     struct wl_private       *lp = wl_priv(dev);
609     struct net_device_stats *pStats = NULL;
610     /*------------------------------------------------------------------------*/
611 
612     DBG_FUNC( "wl_tx_timeout" );
613     DBG_ENTER( DbgInfo );
614 
615     DBG_WARNING( DbgInfo, "%s: Transmit timeout.\n", dev->name );
616 
617     wl_lock( lp, &flags );
618 
619 #ifdef USE_RTS
620     if( lp->useRTS == 1 ) {
621 	DBG_TRACE( DbgInfo, "Skipping tx_timeout handler, in RTS mode\n" );
622 	wl_unlock( lp, &flags );
623 
624 	DBG_LEAVE( DbgInfo );
625 	return;
626     }
627 #endif  /* USE_RTS */
628 
629     /* Figure out which device (the "root" device or WDS port) this timeout
630        is for */
631 #ifdef USE_WDS
632 
633     for( count = 0; count < NUM_WDS_PORTS; count++ ) {
634 	if( dev == lp->wds_port[count].dev ) {
635 	    pStats = &( lp->wds_port[count].stats );
636 
637 	    /* Break the loop so that we can use the counter to access WDS
638 	       information in the private structure */
639 	    break;
640 	}
641     }
642 
643 #endif  /* USE_WDS */
644 
645     /* If pStats is still NULL, then the device is not a WDS port */
646     if( pStats == NULL ) {
647 	pStats = &( lp->stats );
648     }
649 
650     /* Accumulate the timeout error */
651     pStats->tx_errors++;
652 
653     wl_unlock( lp, &flags );
654 
655     DBG_LEAVE( DbgInfo );
656     return;
657 } // wl_tx_timeout
658 /*============================================================================*/
659 
660 /*******************************************************************************
661  *	wl_send()
662  *******************************************************************************
663  *
664  *  DESCRIPTION:
665  *
666  *      The routine which performs data transmits.
667  *
668  *  PARAMETERS:
669  *
670  *      lp  - a pointer to the device's wl_private struct.
671  *
672  *  RETURNS:
673  *
674  *      0 on success
675  *      1 on error
676  *
677  ******************************************************************************/
wl_send(struct wl_private * lp)678 int wl_send( struct wl_private *lp )
679 {
680 
681     int                 status;
682     DESC_STRCT          *desc;
683     WVLAN_LFRAME        *txF = NULL;
684     struct list_head    *element;
685     int                 len;
686     /*------------------------------------------------------------------------*/
687 
688     DBG_FUNC( "wl_send" );
689 
690     if( lp == NULL ) {
691         DBG_ERROR( DbgInfo, "Private adapter struct is NULL\n" );
692         return FALSE;
693     }
694     if( lp->dev == NULL ) {
695         DBG_ERROR( DbgInfo, "net_device struct in wl_private is NULL\n" );
696         return FALSE;
697     }
698 
699     /* Check for the availability of FIDs; if none are available, don't take any
700        frames off the txQ */
701     if( lp->hcfCtx.IFB_RscInd == 0 ) {
702         return FALSE;
703     }
704 
705     /* Reclaim the TxQ Elements and place them back on the free queue */
706     if( !list_empty( &( lp->txQ[0] ))) {
707         element = lp->txQ[0].next;
708 
709         txF = (WVLAN_LFRAME * )list_entry( element, WVLAN_LFRAME, node );
710         if( txF != NULL ) {
711             lp->txF.skb  = txF->frame.skb;
712             lp->txF.port = txF->frame.port;
713 
714             txF->frame.skb  = NULL;
715             txF->frame.port = 0;
716 
717             list_del( &( txF->node ));
718             list_add( element, &( lp->txFree ));
719 
720             lp->txQ_count--;
721 
722             if( lp->txQ_count < TX_Q_LOW_WATER_MARK ) {
723                 if( lp->netif_queue_on == FALSE ) {
724                     DBG_TX( DbgInfo, "Kickstarting Q: %d\n", lp->txQ_count );
725                     netif_wake_queue( lp->dev );
726                     WL_WDS_NETIF_WAKE_QUEUE( lp );
727                     lp->netif_queue_on = TRUE;
728                 }
729             }
730         }
731     }
732 
733     if( lp->txF.skb == NULL ) {
734         return FALSE;
735     }
736 
737     /* If the device has resources (FIDs) available, then Tx the packet */
738     /* Format the TxRequest and send it to the adapter */
739     len = lp->txF.skb->len < ETH_ZLEN ? ETH_ZLEN : lp->txF.skb->len;
740 
741     desc                    = &( lp->desc_tx );
742     desc->buf_addr          = lp->txF.skb->data;
743     desc->BUF_CNT           = len;
744     desc->next_desc_addr    = NULL;
745 
746     status = hcf_send_msg( &( lp->hcfCtx ), desc, lp->txF.port );
747 
748     if( status == HCF_SUCCESS ) {
749         lp->dev->trans_start = jiffies;
750 
751         DBG_TX( DbgInfo, "Transmit...\n" );
752 
753         if( lp->txF.port == HCF_PORT_0 ) {
754             lp->stats.tx_packets++;
755             lp->stats.tx_bytes += lp->txF.skb->len;
756         }
757 
758 #ifdef USE_WDS
759         else
760         {
761             lp->wds_port[(( lp->txF.port >> 8 ) - 1)].stats.tx_packets++;
762             lp->wds_port[(( lp->txF.port >> 8 ) - 1)].stats.tx_bytes += lp->txF.skb->len;
763         }
764 
765 #endif  /* USE_WDS */
766 
767         /* Free the skb and perform queue cleanup, as the buffer was
768             transmitted successfully */
769         dev_kfree_skb( lp->txF.skb );
770 
771         lp->txF.skb = NULL;
772         lp->txF.port = 0;
773     }
774 
775     return TRUE;
776 } // wl_send
777 /*============================================================================*/
778 
779 /*******************************************************************************
780  *	wl_tx()
781  *******************************************************************************
782  *
783  *  DESCRIPTION:
784  *
785  *      The Tx handler function for the network layer.
786  *
787  *  PARAMETERS:
788  *
789  *      skb - a pointer to the sk_buff structure containing the data to transfer.
790  *      dev - a pointer to the device's net_device structure.
791  *
792  *  RETURNS:
793  *
794  *      0 on success
795  *      1 on error
796  *
797  ******************************************************************************/
wl_tx(struct sk_buff * skb,struct net_device * dev,int port)798 int wl_tx( struct sk_buff *skb, struct net_device *dev, int port )
799 {
800     unsigned long           flags;
801     struct wl_private       *lp = wl_priv(dev);
802     WVLAN_LFRAME            *txF = NULL;
803     struct list_head        *element;
804     /*------------------------------------------------------------------------*/
805 
806     DBG_FUNC( "wl_tx" );
807 
808     /* Grab the spinlock */
809     wl_lock( lp, &flags );
810 
811     if( lp->flags & WVLAN2_UIL_BUSY ) {
812         DBG_WARNING( DbgInfo, "UIL has device blocked\n" );
813         /* Start dropping packets here??? */
814 	wl_unlock( lp, &flags );
815         return 1;
816     }
817 
818 #ifdef USE_RTS
819     if( lp->useRTS == 1 ) {
820         DBG_PRINT( "RTS: we're getting a Tx...\n" );
821 	wl_unlock( lp, &flags );
822         return 1;
823     }
824 #endif  /* USE_RTS */
825 
826     if( !lp->use_dma ) {
827         /* Get an element from the queue */
828         element = lp->txFree.next;
829         txF = (WVLAN_LFRAME *)list_entry( element, WVLAN_LFRAME, node );
830         if( txF == NULL ) {
831             DBG_ERROR( DbgInfo, "Problem with list_entry\n" );
832 	    wl_unlock( lp, &flags );
833             return 1;
834         }
835         /* Fill out the frame */
836         txF->frame.skb = skb;
837         txF->frame.port = port;
838         /* Move the frame to the txQ */
839         /* NOTE: Here's where we would do priority queueing */
840         list_del( &( txF->node ));
841         list_add( &( txF->node ), &( lp->txQ[0] ));
842 
843         lp->txQ_count++;
844         if( lp->txQ_count >= DEFAULT_NUM_TX_FRAMES ) {
845             DBG_TX( DbgInfo, "Q Full: %d\n", lp->txQ_count );
846             if( lp->netif_queue_on == TRUE ) {
847                 netif_stop_queue( lp->dev );
848                 WL_WDS_NETIF_STOP_QUEUE( lp );
849                 lp->netif_queue_on = FALSE;
850             }
851         }
852     }
853     wl_act_int_off( lp ); /* Disable Interrupts */
854 
855     /* Send the data to the hardware using the appropriate method */
856 #ifdef ENABLE_DMA
857     if( lp->use_dma ) {
858         wl_send_dma( lp, skb, port );
859     }
860     else
861 #endif
862     {
863         wl_send( lp );
864     }
865     /* Re-enable Interrupts, release the spinlock and return */
866     wl_act_int_on( lp );
867     wl_unlock( lp, &flags );
868     return 0;
869 } // wl_tx
870 /*============================================================================*/
871 
872 /*******************************************************************************
873  *	wl_rx()
874  *******************************************************************************
875  *
876  *  DESCRIPTION:
877  *
878  *      The routine which performs data reception.
879  *
880  *  PARAMETERS:
881  *
882  *      dev - a pointer to the device's net_device structure.
883  *
884  *  RETURNS:
885  *
886  *      0 on success
887  *      1 on error
888  *
889  ******************************************************************************/
wl_rx(struct net_device * dev)890 int wl_rx(struct net_device *dev)
891 {
892     int                     port;
893     struct sk_buff          *skb;
894     struct wl_private       *lp = wl_priv(dev);
895     int                     status;
896     hcf_16                  pktlen;
897     hcf_16                  hfs_stat;
898     DESC_STRCT              *desc;
899     /*------------------------------------------------------------------------*/
900 
901     DBG_FUNC("wl_rx")
902     DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
903 
904     if(!( lp->flags & WVLAN2_UIL_BUSY )) {
905 
906 #ifdef USE_RTS
907         if( lp->useRTS == 1 ) {
908             DBG_PRINT( "RTS: We're getting an Rx...\n" );
909             return -EIO;
910         }
911 #endif  /* USE_RTS */
912 
913         /* Read the HFS_STAT register from the lookahead buffer */
914         hfs_stat = (hcf_16)(( lp->lookAheadBuf[HFS_STAT] ) |
915                             ( lp->lookAheadBuf[HFS_STAT + 1] << 8 ));
916 
917         /* Make sure the frame isn't bad */
918         if(( hfs_stat & HFS_STAT_ERR ) != HCF_SUCCESS ) {
919             DBG_WARNING( DbgInfo, "HFS_STAT_ERROR (0x%x) in Rx Packet\n",
920                          lp->lookAheadBuf[HFS_STAT] );
921             return -EIO;
922         }
923 
924         /* Determine what port this packet is for */
925         port = ( hfs_stat >> 8 ) & 0x0007;
926         DBG_RX( DbgInfo, "Rx frame for port %d\n", port );
927 
928         pktlen = lp->hcfCtx.IFB_RxLen;
929         if (pktlen != 0) {
930             skb = ALLOC_SKB(pktlen);
931             if (skb != NULL) {
932                 /* Set the netdev based on the port */
933                 switch( port ) {
934 #ifdef USE_WDS
935                 case 1:
936                 case 2:
937                 case 3:
938                 case 4:
939                 case 5:
940                 case 6:
941                     skb->dev = lp->wds_port[port-1].dev;
942                     break;
943 #endif  /* USE_WDS */
944 
945                 case 0:
946                 default:
947                     skb->dev = dev;
948                     break;
949                 }
950 
951                 desc = &( lp->desc_rx );
952 
953                 desc->next_desc_addr = NULL;
954 
955 /*
956 #define BLOCK_INPUT(buf, len) \
957     desc->buf_addr = buf; \
958     desc->BUF_SIZE = len; \
959     status = hcf_rcv_msg(&(lp->hcfCtx), desc, 0)
960 */
961 
962                 GET_PACKET( skb->dev, skb, pktlen );
963 
964                 if( status == HCF_SUCCESS ) {
965                     netif_rx( skb );
966 
967                     if( port == 0 ) {
968                         lp->stats.rx_packets++;
969                         lp->stats.rx_bytes += pktlen;
970                     }
971 #ifdef USE_WDS
972                     else
973                     {
974                         lp->wds_port[port-1].stats.rx_packets++;
975                         lp->wds_port[port-1].stats.rx_bytes += pktlen;
976                     }
977 #endif  /* USE_WDS */
978 
979                     dev->last_rx = jiffies;
980 
981 #ifdef WIRELESS_EXT
982 #ifdef WIRELESS_SPY
983                     if( lp->spydata.spy_number > 0 ) {
984                         char *srcaddr = skb->mac.raw + MAC_ADDR_SIZE;
985 
986                         wl_spy_gather( dev, srcaddr );
987                     }
988 #endif /* WIRELESS_SPY */
989 #endif /* WIRELESS_EXT */
990                 } else {
991                     DBG_ERROR( DbgInfo, "Rx request to card FAILED\n" );
992 
993                     if( port == 0 ) {
994                         lp->stats.rx_dropped++;
995                     }
996 #ifdef USE_WDS
997                     else
998                     {
999                         lp->wds_port[port-1].stats.rx_dropped++;
1000                     }
1001 #endif  /* USE_WDS */
1002 
1003                     dev_kfree_skb( skb );
1004                 }
1005             } else {
1006                 DBG_ERROR( DbgInfo, "Could not alloc skb\n" );
1007 
1008                 if( port == 0 ) {
1009                     lp->stats.rx_dropped++;
1010                 }
1011 #ifdef USE_WDS
1012                 else
1013                 {
1014                     lp->wds_port[port-1].stats.rx_dropped++;
1015                 }
1016 #endif  /* USE_WDS */
1017             }
1018         }
1019     }
1020 
1021     return 0;
1022 } // wl_rx
1023 /*============================================================================*/
1024 
1025 /*******************************************************************************
1026  *	wl_multicast()
1027  *******************************************************************************
1028  *
1029  *  DESCRIPTION:
1030  *
1031  *      Function to handle multicast packets
1032  *
1033  *  PARAMETERS:
1034  *
1035  *      dev - a pointer to the device's net_device structure.
1036  *
1037  *  RETURNS:
1038  *
1039  *      N/A
1040  *
1041  ******************************************************************************/
1042 #ifdef NEW_MULTICAST
1043 
wl_multicast(struct net_device * dev)1044 void wl_multicast( struct net_device *dev )
1045 {
1046 #if 1 //;? (HCF_TYPE) & HCF_TYPE_STA //;?should we return an error status in AP mode
1047 //;?seems reasonable that even an AP-only driver could afford this small additional footprint
1048 
1049     int                 x;
1050     struct netdev_hw_addr *ha;
1051     struct wl_private   *lp = wl_priv(dev);
1052     unsigned long       flags;
1053     /*------------------------------------------------------------------------*/
1054 
1055     DBG_FUNC( "wl_multicast" );
1056     DBG_ENTER( DbgInfo );
1057     DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
1058 
1059     if( !wl_adapter_is_open( dev )) {
1060         DBG_LEAVE( DbgInfo );
1061         return;
1062     }
1063 
1064 #if DBG
1065     if( DBG_FLAGS( DbgInfo ) & DBG_PARAM_ON ) {
1066         DBG_PRINT("  flags: %s%s%s\n",
1067             ( dev->flags & IFF_PROMISC ) ? "Promiscous " : "",
1068             ( dev->flags & IFF_MULTICAST ) ? "Multicast " : "",
1069             ( dev->flags & IFF_ALLMULTI ) ? "All-Multicast" : "" );
1070 
1071         DBG_PRINT( "  mc_count: %d\n", netdev_mc_count(dev));
1072 
1073 	netdev_for_each_mc_addr(ha, dev)
1074 	DBG_PRINT("    %pM (%d)\n", ha->addr, dev->addr_len);
1075     }
1076 #endif /* DBG */
1077 
1078     if(!( lp->flags & WVLAN2_UIL_BUSY )) {
1079 
1080 #ifdef USE_RTS
1081         if( lp->useRTS == 1 ) {
1082             DBG_TRACE( DbgInfo, "Skipping multicast, in RTS mode\n" );
1083 
1084             DBG_LEAVE( DbgInfo );
1085             return;
1086         }
1087 #endif  /* USE_RTS */
1088 
1089         wl_lock( lp, &flags );
1090         wl_act_int_off( lp );
1091 
1092 		if ( CNV_INT_TO_LITTLE( lp->hcfCtx.IFB_FWIdentity.comp_id ) == COMP_ID_FW_STA  ) {
1093             if( dev->flags & IFF_PROMISC ) {
1094                 /* Enable promiscuous mode */
1095                 lp->ltvRecord.len       = 2;
1096                 lp->ltvRecord.typ       = CFG_PROMISCUOUS_MODE;
1097                 lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 1 );
1098                 DBG_PRINT( "Enabling Promiscuous mode (IFF_PROMISC)\n" );
1099                 hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1100             }
1101             else if ((netdev_mc_count(dev) > HCF_MAX_MULTICAST) ||
1102                     ( dev->flags & IFF_ALLMULTI )) {
1103                 /* Shutting off this filter will enable all multicast frames to
1104                    be sent up from the device; however, this is a static RID, so
1105                    a call to wl_apply() is needed */
1106                 lp->ltvRecord.len       = 2;
1107                 lp->ltvRecord.typ       = CFG_CNF_RX_ALL_GROUP_ADDR;
1108                 lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0 );
1109                 DBG_PRINT( "Enabling all multicast mode (IFF_ALLMULTI)\n" );
1110                 hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1111                 wl_apply( lp );
1112             }
1113             else if (!netdev_mc_empty(dev)) {
1114                 /* Set the multicast addresses */
1115                 lp->ltvRecord.len = ( netdev_mc_count(dev) * 3 ) + 1;
1116                 lp->ltvRecord.typ = CFG_GROUP_ADDR;
1117 
1118 		x = 0;
1119 		netdev_for_each_mc_addr(ha, dev)
1120                     memcpy(&(lp->ltvRecord.u.u8[x++ * ETH_ALEN]),
1121 			   ha->addr, ETH_ALEN);
1122                 DBG_PRINT( "Setting multicast list\n" );
1123                 hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1124             } else {
1125                 /* Disable promiscuous mode */
1126                 lp->ltvRecord.len       = 2;
1127                 lp->ltvRecord.typ       = CFG_PROMISCUOUS_MODE;
1128                 lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 0 );
1129                 DBG_PRINT( "Disabling Promiscuous mode\n" );
1130                 hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1131 
1132                 /* Disable multicast mode */
1133                 lp->ltvRecord.len = 2;
1134                 lp->ltvRecord.typ = CFG_GROUP_ADDR;
1135                 DBG_PRINT( "Disabling Multicast mode\n" );
1136                 hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1137 
1138                 /* Turning on this filter will prevent all multicast frames from
1139                    being sent up from the device; however, this is a static RID,
1140                    so a call to wl_apply() is needed */
1141                 lp->ltvRecord.len       = 2;
1142                 lp->ltvRecord.typ       = CFG_CNF_RX_ALL_GROUP_ADDR;
1143                 lp->ltvRecord.u.u16[0]  = CNV_INT_TO_LITTLE( 1 );
1144                 DBG_PRINT( "Disabling all multicast mode (IFF_ALLMULTI)\n" );
1145                 hcf_put_info( &( lp->hcfCtx ), (LTVP)&( lp->ltvRecord ));
1146                 wl_apply( lp );
1147             }
1148         }
1149         wl_act_int_on( lp );
1150 	wl_unlock( lp, &flags );
1151     }
1152     DBG_LEAVE( DbgInfo );
1153 #endif /* HCF_STA */
1154 } // wl_multicast
1155 /*============================================================================*/
1156 
1157 #else /* NEW_MULTICAST */
1158 
wl_multicast(struct net_device * dev,int num_addrs,void * addrs)1159 void wl_multicast( struct net_device *dev, int num_addrs, void *addrs )
1160 {
1161     DBG_FUNC( "wl_multicast");
1162     DBG_ENTER(DbgInfo);
1163 
1164     DBG_PARAM( DbgInfo, "dev", "%s (0x%p)", dev->name, dev );
1165     DBG_PARAM( DbgInfo, "num_addrs", "%d", num_addrs );
1166     DBG_PARAM( DbgInfo, "addrs", "0x%p", addrs );
1167 
1168 #error Obsolete set multicast interface!
1169 
1170     DBG_LEAVE( DbgInfo );
1171 } // wl_multicast
1172 /*============================================================================*/
1173 
1174 #endif /* NEW_MULTICAST */
1175 
1176 static const struct net_device_ops wl_netdev_ops =
1177 {
1178     .ndo_start_xmit         = &wl_tx_port0,
1179 
1180     .ndo_set_config         = &wl_config,
1181     .ndo_get_stats          = &wl_stats,
1182     .ndo_set_multicast_list = &wl_multicast,
1183 
1184     .ndo_init               = &wl_insert,
1185     .ndo_open               = &wl_adapter_open,
1186     .ndo_stop               = &wl_adapter_close,
1187     .ndo_do_ioctl           = &wl_ioctl,
1188 
1189     .ndo_tx_timeout         = &wl_tx_timeout,
1190 
1191 #ifdef CONFIG_NET_POLL_CONTROLLER
1192     .ndo_poll_controller    = wl_poll,
1193 #endif
1194 };
1195 
1196 /*******************************************************************************
1197  *	wl_device_alloc()
1198  *******************************************************************************
1199  *
1200  *  DESCRIPTION:
1201  *
1202  *      Create instances of net_device and wl_private for the new adapter
1203  *  and register the device's entry points in the net_device structure.
1204  *
1205  *  PARAMETERS:
1206  *
1207  *      N/A
1208  *
1209  *  RETURNS:
1210  *
1211  *      a pointer to an allocated and initialized net_device struct for this
1212  *      device.
1213  *
1214  ******************************************************************************/
wl_device_alloc(void)1215 struct net_device * wl_device_alloc( void )
1216 {
1217     struct net_device   *dev = NULL;
1218     struct wl_private   *lp = NULL;
1219     /*------------------------------------------------------------------------*/
1220 
1221     DBG_FUNC( "wl_device_alloc" );
1222     DBG_ENTER( DbgInfo );
1223 
1224     /* Alloc a net_device struct */
1225     dev = alloc_etherdev(sizeof(struct wl_private));
1226     if (!dev)
1227         return NULL;
1228 
1229     /* Initialize the 'next' pointer in the struct. Currently only used for PCI,
1230        but do it here just in case it's used for other buses in the future */
1231     lp = wl_priv(dev);
1232 
1233 
1234     /* Check MTU */
1235     if( dev->mtu > MTU_MAX )
1236     {
1237 	    DBG_WARNING( DbgInfo, "%s: MTU set too high, limiting to %d.\n",
1238                         dev->name, MTU_MAX );
1239     	dev->mtu = MTU_MAX;
1240     }
1241 
1242     /* Setup the function table in the device structure. */
1243 
1244     dev->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def;
1245     lp->wireless_data.spy_data = &lp->spy_data;
1246     dev->wireless_data = &lp->wireless_data;
1247 
1248     dev->netdev_ops = &wl_netdev_ops;
1249 
1250     dev->watchdog_timeo     = TX_TIMEOUT;
1251 
1252     dev->ethtool_ops	    = &wl_ethtool_ops;
1253 
1254     netif_stop_queue( dev );
1255 
1256     /* Allocate virutal devices for WDS support if needed */
1257     WL_WDS_DEVICE_ALLOC( lp );
1258 
1259     DBG_LEAVE( DbgInfo );
1260     return dev;
1261 } // wl_device_alloc
1262 /*============================================================================*/
1263 
1264 /*******************************************************************************
1265  *	wl_device_dealloc()
1266  *******************************************************************************
1267  *
1268  *  DESCRIPTION:
1269  *
1270  *      Free instances of net_device and wl_private strcutres for an adapter
1271  *  and perform basic cleanup.
1272  *
1273  *  PARAMETERS:
1274  *
1275  *      dev - a pointer to the device's net_device structure.
1276  *
1277  *  RETURNS:
1278  *
1279  *      N/A
1280  *
1281  ******************************************************************************/
wl_device_dealloc(struct net_device * dev)1282 void wl_device_dealloc( struct net_device *dev )
1283 {
1284 //    struct wl_private   *lp = wl_priv(dev);
1285     /*------------------------------------------------------------------------*/
1286 
1287     DBG_FUNC( "wl_device_dealloc" );
1288     DBG_ENTER( DbgInfo );
1289 
1290     /* Dealloc the WDS ports */
1291     WL_WDS_DEVICE_DEALLOC( lp );
1292 
1293     free_netdev( dev );
1294 
1295     DBG_LEAVE( DbgInfo );
1296     return;
1297 } // wl_device_dealloc
1298 /*============================================================================*/
1299 
1300 /*******************************************************************************
1301  *	wl_tx_port0()
1302  *******************************************************************************
1303  *
1304  *  DESCRIPTION:
1305  *
1306  *      The handler routine for Tx over HCF_PORT_0.
1307  *
1308  *  PARAMETERS:
1309  *
1310  *      skb - a pointer to the sk_buff to transmit.
1311  *      dev - a pointer to a net_device structure representing HCF_PORT_0.
1312  *
1313  *  RETURNS:
1314  *
1315  *      N/A
1316  *
1317  ******************************************************************************/
wl_tx_port0(struct sk_buff * skb,struct net_device * dev)1318 int wl_tx_port0( struct sk_buff *skb, struct net_device *dev )
1319 {
1320     DBG_TX( DbgInfo, "Tx on Port 0\n" );
1321 
1322     return wl_tx( skb, dev, HCF_PORT_0 );
1323 #ifdef ENABLE_DMA
1324     return wl_tx_dma( skb, dev, HCF_PORT_0 );
1325 #endif
1326 } // wl_tx_port0
1327 /*============================================================================*/
1328 
1329 #ifdef USE_WDS
1330 
1331 /*******************************************************************************
1332  *	wl_tx_port1()
1333  *******************************************************************************
1334  *
1335  *  DESCRIPTION:
1336  *
1337  *      The handler routine for Tx over HCF_PORT_1.
1338  *
1339  *  PARAMETERS:
1340  *
1341  *      skb - a pointer to the sk_buff to transmit.
1342  *      dev - a pointer to a net_device structure representing HCF_PORT_1.
1343  *
1344  *  RETURNS:
1345  *
1346  *      N/A
1347  *
1348  ******************************************************************************/
wl_tx_port1(struct sk_buff * skb,struct net_device * dev)1349 int wl_tx_port1( struct sk_buff *skb, struct net_device *dev )
1350 {
1351     DBG_TX( DbgInfo, "Tx on Port 1\n" );
1352     return wl_tx( skb, dev, HCF_PORT_1 );
1353 } // wl_tx_port1
1354 /*============================================================================*/
1355 
1356 /*******************************************************************************
1357  *	wl_tx_port2()
1358  *******************************************************************************
1359  *
1360  *  DESCRIPTION:
1361  *
1362  *      The handler routine for Tx over HCF_PORT_2.
1363  *
1364  *  PARAMETERS:
1365  *
1366  *      skb - a pointer to the sk_buff to transmit.
1367  *      dev - a pointer to a net_device structure representing HCF_PORT_2.
1368  *
1369  *  RETURNS:
1370  *
1371  *      N/A
1372  *
1373  ******************************************************************************/
wl_tx_port2(struct sk_buff * skb,struct net_device * dev)1374 int wl_tx_port2( struct sk_buff *skb, struct net_device *dev )
1375 {
1376     DBG_TX( DbgInfo, "Tx on Port 2\n" );
1377     return wl_tx( skb, dev, HCF_PORT_2 );
1378 } // wl_tx_port2
1379 /*============================================================================*/
1380 
1381 /*******************************************************************************
1382  *	wl_tx_port3()
1383  *******************************************************************************
1384  *
1385  *  DESCRIPTION:
1386  *
1387  *      The handler routine for Tx over HCF_PORT_3.
1388  *
1389  *  PARAMETERS:
1390  *
1391  *      skb - a pointer to the sk_buff to transmit.
1392  *      dev - a pointer to a net_device structure representing HCF_PORT_3.
1393  *
1394  *  RETURNS:
1395  *
1396  *      N/A
1397  *
1398  ******************************************************************************/
wl_tx_port3(struct sk_buff * skb,struct net_device * dev)1399 int wl_tx_port3( struct sk_buff *skb, struct net_device *dev )
1400 {
1401     DBG_TX( DbgInfo, "Tx on Port 3\n" );
1402     return wl_tx( skb, dev, HCF_PORT_3 );
1403 } // wl_tx_port3
1404 /*============================================================================*/
1405 
1406 /*******************************************************************************
1407  *	wl_tx_port4()
1408  *******************************************************************************
1409  *
1410  *  DESCRIPTION:
1411  *
1412  *      The handler routine for Tx over HCF_PORT_4.
1413  *
1414  *  PARAMETERS:
1415  *
1416  *      skb - a pointer to the sk_buff to transmit.
1417  *      dev - a pointer to a net_device structure representing HCF_PORT_4.
1418  *
1419  *  RETURNS:
1420  *
1421  *      N/A
1422  *
1423  ******************************************************************************/
wl_tx_port4(struct sk_buff * skb,struct net_device * dev)1424 int wl_tx_port4( struct sk_buff *skb, struct net_device *dev )
1425 {
1426     DBG_TX( DbgInfo, "Tx on Port 4\n" );
1427     return wl_tx( skb, dev, HCF_PORT_4 );
1428 } // wl_tx_port4
1429 /*============================================================================*/
1430 
1431 /*******************************************************************************
1432  *	wl_tx_port5()
1433  *******************************************************************************
1434  *
1435  *  DESCRIPTION:
1436  *
1437  *      The handler routine for Tx over HCF_PORT_5.
1438  *
1439  *  PARAMETERS:
1440  *
1441  *      skb - a pointer to the sk_buff to transmit.
1442  *      dev - a pointer to a net_device structure representing HCF_PORT_5.
1443  *
1444  *  RETURNS:
1445  *
1446  *      N/A
1447  *
1448  ******************************************************************************/
wl_tx_port5(struct sk_buff * skb,struct net_device * dev)1449 int wl_tx_port5( struct sk_buff *skb, struct net_device *dev )
1450 {
1451     DBG_TX( DbgInfo, "Tx on Port 5\n" );
1452     return wl_tx( skb, dev, HCF_PORT_5 );
1453 } // wl_tx_port5
1454 /*============================================================================*/
1455 
1456 /*******************************************************************************
1457  *	wl_tx_port6()
1458  *******************************************************************************
1459  *
1460  *  DESCRIPTION:
1461  *
1462  *      The handler routine for Tx over HCF_PORT_6.
1463  *
1464  *  PARAMETERS:
1465  *
1466  *      skb - a pointer to the sk_buff to transmit.
1467  *      dev - a pointer to a net_device structure representing HCF_PORT_6.
1468  *
1469  *  RETURNS:
1470  *
1471  *      N/A
1472  *
1473  ******************************************************************************/
wl_tx_port6(struct sk_buff * skb,struct net_device * dev)1474 int wl_tx_port6( struct sk_buff *skb, struct net_device *dev )
1475 {
1476     DBG_TX( DbgInfo, "Tx on Port 6\n" );
1477     return wl_tx( skb, dev, HCF_PORT_6 );
1478 } // wl_tx_port6
1479 /*============================================================================*/
1480 
1481 /*******************************************************************************
1482  *	wl_wds_device_alloc()
1483  *******************************************************************************
1484  *
1485  *  DESCRIPTION:
1486  *
1487  *      Create instances of net_device to represent the WDS ports, and register
1488  *  the device's entry points in the net_device structure.
1489  *
1490  *  PARAMETERS:
1491  *
1492  *      lp  - a pointer to the device's private adapter structure
1493  *
1494  *  RETURNS:
1495  *
1496  *      N/A, but will place pointers to the allocated and initialized net_device
1497  *      structs in the private adapter structure.
1498  *
1499  ******************************************************************************/
wl_wds_device_alloc(struct wl_private * lp)1500 void wl_wds_device_alloc( struct wl_private *lp )
1501 {
1502     int count;
1503     /*------------------------------------------------------------------------*/
1504 
1505     DBG_FUNC( "wl_wds_device_alloc" );
1506     DBG_ENTER( DbgInfo );
1507 
1508     /* WDS support requires additional net_device structs to be allocated,
1509        so that user space apps can use these virtual devices to specify the
1510        port on which to Tx/Rx */
1511     for( count = 0; count < NUM_WDS_PORTS; count++ ) {
1512         struct net_device *dev_wds = NULL;
1513 
1514         dev_wds = kmalloc( sizeof( struct net_device ), GFP_KERNEL );
1515         memset( dev_wds, 0, sizeof( struct net_device ));
1516 
1517         ether_setup( dev_wds );
1518 
1519         lp->wds_port[count].dev = dev_wds;
1520 
1521         /* Re-use wl_init for all the devices, as it currently does nothing, but
1522            is required. Re-use the stats/tx_timeout handler for all as well; the
1523            WDS port which is requesting these operations can be determined by
1524            the net_device pointer. Set the private member of all devices to point
1525            to the same net_device struct; that way, all information gets
1526            funnelled through the one "real" net_device. Name the WDS ports
1527            "wds<n>" */
1528         lp->wds_port[count].dev->init           = &wl_init;
1529         lp->wds_port[count].dev->get_stats      = &wl_stats;
1530         lp->wds_port[count].dev->tx_timeout     = &wl_tx_timeout;
1531         lp->wds_port[count].dev->watchdog_timeo = TX_TIMEOUT;
1532         lp->wds_port[count].dev->priv           = lp;
1533 
1534         sprintf( lp->wds_port[count].dev->name, "wds%d", count );
1535     }
1536 
1537     /* Register the Tx handlers */
1538     lp->wds_port[0].dev->hard_start_xmit = &wl_tx_port1;
1539     lp->wds_port[1].dev->hard_start_xmit = &wl_tx_port2;
1540     lp->wds_port[2].dev->hard_start_xmit = &wl_tx_port3;
1541     lp->wds_port[3].dev->hard_start_xmit = &wl_tx_port4;
1542     lp->wds_port[4].dev->hard_start_xmit = &wl_tx_port5;
1543     lp->wds_port[5].dev->hard_start_xmit = &wl_tx_port6;
1544 
1545     WL_WDS_NETIF_STOP_QUEUE( lp );
1546 
1547     DBG_LEAVE( DbgInfo );
1548     return;
1549 } // wl_wds_device_alloc
1550 /*============================================================================*/
1551 
1552 /*******************************************************************************
1553  *	wl_wds_device_dealloc()
1554  *******************************************************************************
1555  *
1556  *  DESCRIPTION:
1557  *
1558  *      Free instances of net_device structures used to support WDS.
1559  *
1560  *  PARAMETERS:
1561  *
1562  *      lp  - a pointer to the device's private adapter structure
1563  *
1564  *  RETURNS:
1565  *
1566  *      N/A
1567  *
1568  ******************************************************************************/
wl_wds_device_dealloc(struct wl_private * lp)1569 void wl_wds_device_dealloc( struct wl_private *lp )
1570 {
1571     int count;
1572     /*------------------------------------------------------------------------*/
1573 
1574     DBG_FUNC( "wl_wds_device_dealloc" );
1575     DBG_ENTER( DbgInfo );
1576 
1577     for( count = 0; count < NUM_WDS_PORTS; count++ ) {
1578         struct net_device *dev_wds = NULL;
1579 
1580         dev_wds = lp->wds_port[count].dev;
1581 
1582         if( dev_wds != NULL ) {
1583             if( dev_wds->flags & IFF_UP ) {
1584                 dev_close( dev_wds );
1585                 dev_wds->flags &= ~( IFF_UP | IFF_RUNNING );
1586             }
1587 
1588             free_netdev(dev_wds);
1589             lp->wds_port[count].dev = NULL;
1590         }
1591     }
1592 
1593     DBG_LEAVE( DbgInfo );
1594     return;
1595 } // wl_wds_device_dealloc
1596 /*============================================================================*/
1597 
1598 /*******************************************************************************
1599  *	wl_wds_netif_start_queue()
1600  *******************************************************************************
1601  *
1602  *  DESCRIPTION:
1603  *
1604  *      Used to start the netif queues of all the "virtual" network devices
1605  *      which repesent the WDS ports.
1606  *
1607  *  PARAMETERS:
1608  *
1609  *      lp  - a pointer to the device's private adapter structure
1610  *
1611  *  RETURNS:
1612  *
1613  *      N/A
1614  *
1615  ******************************************************************************/
wl_wds_netif_start_queue(struct wl_private * lp)1616 void wl_wds_netif_start_queue( struct wl_private *lp )
1617 {
1618     int count;
1619     /*------------------------------------------------------------------------*/
1620 
1621     if( lp != NULL ) {
1622         for( count = 0; count < NUM_WDS_PORTS; count++ ) {
1623             if( lp->wds_port[count].is_registered &&
1624                 lp->wds_port[count].netif_queue_on == FALSE ) {
1625                 netif_start_queue( lp->wds_port[count].dev );
1626                 lp->wds_port[count].netif_queue_on = TRUE;
1627             }
1628         }
1629     }
1630 
1631     return;
1632 } // wl_wds_netif_start_queue
1633 /*============================================================================*/
1634 
1635 /*******************************************************************************
1636  *	wl_wds_netif_stop_queue()
1637  *******************************************************************************
1638  *
1639  *  DESCRIPTION:
1640  *
1641  *      Used to stop the netif queues of all the "virtual" network devices
1642  *      which repesent the WDS ports.
1643  *
1644  *  PARAMETERS:
1645  *
1646  *      lp  - a pointer to the device's private adapter structure
1647  *
1648  *  RETURNS:
1649  *
1650  *      N/A
1651  *
1652  ******************************************************************************/
wl_wds_netif_stop_queue(struct wl_private * lp)1653 void wl_wds_netif_stop_queue( struct wl_private *lp )
1654 {
1655     int count;
1656     /*------------------------------------------------------------------------*/
1657 
1658     if( lp != NULL ) {
1659         for( count = 0; count < NUM_WDS_PORTS; count++ ) {
1660             if( lp->wds_port[count].is_registered &&
1661                 lp->wds_port[count].netif_queue_on == TRUE ) {
1662                 netif_stop_queue( lp->wds_port[count].dev );
1663                 lp->wds_port[count].netif_queue_on = FALSE;
1664             }
1665         }
1666     }
1667 
1668     return;
1669 } // wl_wds_netif_stop_queue
1670 /*============================================================================*/
1671 
1672 /*******************************************************************************
1673  *	wl_wds_netif_wake_queue()
1674  *******************************************************************************
1675  *
1676  *  DESCRIPTION:
1677  *
1678  *      Used to wake the netif queues of all the "virtual" network devices
1679  *      which repesent the WDS ports.
1680  *
1681  *  PARAMETERS:
1682  *
1683  *      lp  - a pointer to the device's private adapter structure
1684  *
1685  *  RETURNS:
1686  *
1687  *      N/A
1688  *
1689  ******************************************************************************/
wl_wds_netif_wake_queue(struct wl_private * lp)1690 void wl_wds_netif_wake_queue( struct wl_private *lp )
1691 {
1692     int count;
1693     /*------------------------------------------------------------------------*/
1694 
1695     if( lp != NULL ) {
1696         for( count = 0; count < NUM_WDS_PORTS; count++ ) {
1697             if( lp->wds_port[count].is_registered &&
1698                 lp->wds_port[count].netif_queue_on == FALSE ) {
1699                 netif_wake_queue( lp->wds_port[count].dev );
1700                 lp->wds_port[count].netif_queue_on = TRUE;
1701             }
1702         }
1703     }
1704 
1705     return;
1706 } // wl_wds_netif_wake_queue
1707 /*============================================================================*/
1708 
1709 /*******************************************************************************
1710  *	wl_wds_netif_carrier_on()
1711  *******************************************************************************
1712  *
1713  *  DESCRIPTION:
1714  *
1715  *      Used to signal the network layer that carrier is present on all of the
1716  *      "virtual" network devices which repesent the WDS ports.
1717  *
1718  *  PARAMETERS:
1719  *
1720  *      lp  - a pointer to the device's private adapter structure
1721  *
1722  *  RETURNS:
1723  *
1724  *      N/A
1725  *
1726  ******************************************************************************/
wl_wds_netif_carrier_on(struct wl_private * lp)1727 void wl_wds_netif_carrier_on( struct wl_private *lp )
1728 {
1729     int count;
1730     /*------------------------------------------------------------------------*/
1731 
1732     if( lp != NULL ) {
1733         for( count = 0; count < NUM_WDS_PORTS; count++ ) {
1734             if( lp->wds_port[count].is_registered ) {
1735                 netif_carrier_on( lp->wds_port[count].dev );
1736             }
1737         }
1738     }
1739 
1740     return;
1741 } // wl_wds_netif_carrier_on
1742 /*============================================================================*/
1743 
1744 /*******************************************************************************
1745  *	wl_wds_netif_carrier_off()
1746  *******************************************************************************
1747  *
1748  *  DESCRIPTION:
1749  *
1750  *      Used to signal the network layer that carrier is NOT present on all of
1751  *      the "virtual" network devices which repesent the WDS ports.
1752  *
1753  *  PARAMETERS:
1754  *
1755  *      lp  - a pointer to the device's private adapter structure
1756  *
1757  *  RETURNS:
1758  *
1759  *      N/A
1760  *
1761  ******************************************************************************/
wl_wds_netif_carrier_off(struct wl_private * lp)1762 void wl_wds_netif_carrier_off( struct wl_private *lp )
1763 {
1764     int count;
1765     /*------------------------------------------------------------------------*/
1766 
1767     if( lp != NULL ) {
1768         for( count = 0; count < NUM_WDS_PORTS; count++ ) {
1769             if( lp->wds_port[count].is_registered ) {
1770                 netif_carrier_off( lp->wds_port[count].dev );
1771             }
1772         }
1773     }
1774 
1775     return;
1776 } // wl_wds_netif_carrier_off
1777 /*============================================================================*/
1778 
1779 #endif  /* USE_WDS */
1780 
1781 #ifdef ENABLE_DMA
1782 /*******************************************************************************
1783  *	wl_send_dma()
1784  *******************************************************************************
1785  *
1786  *  DESCRIPTION:
1787  *
1788  *      The routine which performs data transmits when using busmaster DMA.
1789  *
1790  *  PARAMETERS:
1791  *
1792  *      lp   - a pointer to the device's wl_private struct.
1793  *      skb  - a pointer to the network layer's data buffer.
1794  *      port - the Hermes port on which to transmit.
1795  *
1796  *  RETURNS:
1797  *
1798  *      0 on success
1799  *      1 on error
1800  *
1801  ******************************************************************************/
wl_send_dma(struct wl_private * lp,struct sk_buff * skb,int port)1802 int wl_send_dma( struct wl_private *lp, struct sk_buff *skb, int port )
1803 {
1804     int         len;
1805     DESC_STRCT *desc = NULL;
1806     DESC_STRCT *desc_next = NULL;
1807     /*------------------------------------------------------------------------*/
1808 
1809     DBG_FUNC( "wl_send_dma" );
1810 
1811     if( lp == NULL )
1812     {
1813         DBG_ERROR( DbgInfo, "Private adapter struct is NULL\n" );
1814         return FALSE;
1815     }
1816 
1817     if( lp->dev == NULL )
1818     {
1819         DBG_ERROR( DbgInfo, "net_device struct in wl_private is NULL\n" );
1820         return FALSE;
1821     }
1822 
1823     /* AGAIN, ALL THE QUEUEING DONE HERE IN I/O MODE IS NOT PERFORMED */
1824 
1825     if( skb == NULL )
1826     {
1827         DBG_WARNING (DbgInfo, "Nothing to send.\n");
1828         return FALSE;
1829     }
1830 
1831     len = skb->len;
1832 
1833     /* Get a free descriptor */
1834     desc = wl_pci_dma_get_tx_packet( lp );
1835 
1836     if( desc == NULL )
1837     {
1838         if( lp->netif_queue_on == TRUE ) {
1839             netif_stop_queue( lp->dev );
1840             WL_WDS_NETIF_STOP_QUEUE( lp );
1841             lp->netif_queue_on = FALSE;
1842 
1843             dev_kfree_skb( skb );
1844             return 0;
1845         }
1846     }
1847 
1848     SET_BUF_CNT( desc, /*HCF_DMA_FD_CNT*/HFS_ADDR_DEST );
1849     SET_BUF_SIZE( desc, HCF_DMA_TX_BUF1_SIZE );
1850 
1851     desc_next = desc->next_desc_addr;
1852 
1853     if( desc_next->buf_addr == NULL )
1854     {
1855         DBG_ERROR( DbgInfo, "DMA descriptor buf_addr is NULL\n" );
1856         return FALSE;
1857     }
1858 
1859     /* Copy the payload into the DMA packet */
1860     memcpy( desc_next->buf_addr, skb->data, len );
1861 
1862     SET_BUF_CNT( desc_next, len );
1863     SET_BUF_SIZE( desc_next, HCF_MAX_PACKET_SIZE );
1864 
1865     hcf_dma_tx_put( &( lp->hcfCtx ), desc, 0 );
1866 
1867     /* Free the skb and perform queue cleanup, as the buffer was
1868             transmitted successfully */
1869     dev_kfree_skb( skb );
1870 
1871     return TRUE;
1872 } // wl_send_dma
1873 /*============================================================================*/
1874 
1875 /*******************************************************************************
1876  *	wl_rx_dma()
1877  *******************************************************************************
1878  *
1879  *  DESCRIPTION:
1880  *
1881  *      The routine which performs data reception when using busmaster DMA.
1882  *
1883  *  PARAMETERS:
1884  *
1885  *      dev - a pointer to the device's net_device structure.
1886  *
1887  *  RETURNS:
1888  *
1889  *      0 on success
1890  *      1 on error
1891  *
1892  ******************************************************************************/
wl_rx_dma(struct net_device * dev)1893 int wl_rx_dma( struct net_device *dev )
1894 {
1895     int                      port;
1896     hcf_16                   pktlen;
1897     hcf_16                   hfs_stat;
1898     struct sk_buff          *skb;
1899     struct wl_private       *lp = NULL;
1900     DESC_STRCT              *desc, *desc_next;
1901     //CFG_MB_INFO_RANGE2_STRCT x;
1902     /*------------------------------------------------------------------------*/
1903 
1904     DBG_FUNC("wl_rx")
1905     DBG_PARAM(DbgInfo, "dev", "%s (0x%p)", dev->name, dev);
1906 
1907     if((( lp = dev->priv ) != NULL ) &&
1908 	!( lp->flags & WVLAN2_UIL_BUSY )) {
1909 
1910 #ifdef USE_RTS
1911         if( lp->useRTS == 1 ) {
1912             DBG_PRINT( "RTS: We're getting an Rx...\n" );
1913             return -EIO;
1914         }
1915 #endif  /* USE_RTS */
1916 
1917         //if( lp->dma.status == 0 )
1918         //{
1919             desc = hcf_dma_rx_get( &( lp->hcfCtx ));
1920 
1921             if( desc != NULL )
1922             {
1923                 /* Check and see if we rcvd. a WMP frame */
1924                 /*
1925                 if((( *(hcf_8 *)&desc->buf_addr[HFS_STAT] ) &
1926                     ( HFS_STAT_MSG_TYPE | HFS_STAT_ERR )) == HFS_STAT_WMP_MSG )
1927                 {
1928                     DBG_TRACE( DbgInfo, "Got a WMP frame\n" );
1929 
1930                     x.len = sizeof( CFG_MB_INFO_RANGE2_STRCT ) / sizeof( hcf_16 );
1931 				    x.typ = CFG_MB_INFO;
1932 				    x.base_typ = CFG_WMP;
1933 				    x.frag_cnt = 2;
1934 				    x.frag_buf[0].frag_len  = GET_BUF_CNT( descp ) / sizeof( hcf_16 );
1935 				    x.frag_buf[0].frag_addr = (hcf_8 *) descp->buf_addr ;
1936 				    x.frag_buf[1].frag_len  = ( GET_BUF_CNT( descp->next_desc_addr ) + 1 ) / sizeof( hcf_16 );
1937 				    x.frag_buf[1].frag_addr = (hcf_8 *) descp->next_desc_addr->buf_addr ;
1938 
1939                     hcf_put_info( &( lp->hcfCtx ), (LTVP)&x );
1940                 }
1941                 */
1942 
1943                 desc_next = desc->next_desc_addr;
1944 
1945                 /* Make sure the buffer isn't empty */
1946                 if( GET_BUF_CNT( desc ) == 0 ) {
1947                     DBG_WARNING( DbgInfo, "Buffer is empty!\n" );
1948 
1949                     /* Give the descriptor back to the HCF */
1950                     hcf_dma_rx_put( &( lp->hcfCtx ), desc );
1951                     return -EIO;
1952                 }
1953 
1954                 /* Read the HFS_STAT register from the lookahead buffer */
1955                 hfs_stat = (hcf_16)( desc->buf_addr[HFS_STAT/2] );
1956 
1957                 /* Make sure the frame isn't bad */
1958                 if(( hfs_stat & HFS_STAT_ERR ) != HCF_SUCCESS )
1959                 {
1960                     DBG_WARNING( DbgInfo, "HFS_STAT_ERROR (0x%x) in Rx Packet\n",
1961                                 desc->buf_addr[HFS_STAT/2] );
1962 
1963                     /* Give the descriptor back to the HCF */
1964                     hcf_dma_rx_put( &( lp->hcfCtx ), desc );
1965                     return -EIO;
1966                 }
1967 
1968                 /* Determine what port this packet is for */
1969                 port = ( hfs_stat >> 8 ) & 0x0007;
1970                 DBG_RX( DbgInfo, "Rx frame for port %d\n", port );
1971 
1972                 pktlen = GET_BUF_CNT(desc_next);
1973                 if (pktlen != 0) {
1974                     skb = ALLOC_SKB(pktlen);
1975                     if (skb != NULL) {
1976                         switch( port ) {
1977 #ifdef USE_WDS
1978                         case 1:
1979                         case 2:
1980                         case 3:
1981                         case 4:
1982                         case 5:
1983                         case 6:
1984                             skb->dev = lp->wds_port[port-1].dev;
1985                             break;
1986 #endif  /* USE_WDS */
1987 
1988                         case 0:
1989                         default:
1990                             skb->dev = dev;
1991                             break;
1992                         }
1993 
1994                         GET_PACKET_DMA( skb->dev, skb, pktlen );
1995 
1996                         /* Give the descriptor back to the HCF */
1997                         hcf_dma_rx_put( &( lp->hcfCtx ), desc );
1998 
1999                         netif_rx( skb );
2000 
2001                         if( port == 0 ) {
2002                             lp->stats.rx_packets++;
2003                             lp->stats.rx_bytes += pktlen;
2004                         }
2005 #ifdef USE_WDS
2006                         else
2007                         {
2008                             lp->wds_port[port-1].stats.rx_packets++;
2009                             lp->wds_port[port-1].stats.rx_bytes += pktlen;
2010                         }
2011 #endif  /* USE_WDS */
2012 
2013                         dev->last_rx = jiffies;
2014 
2015                     } else {
2016                         DBG_ERROR( DbgInfo, "Could not alloc skb\n" );
2017 
2018                         if( port == 0 )
2019 	                    {
2020 	                        lp->stats.rx_dropped++;
2021 	                    }
2022 #ifdef USE_WDS
2023                         else
2024                         {
2025                             lp->wds_port[port-1].stats.rx_dropped++;
2026                         }
2027 #endif  /* USE_WDS */
2028                     }
2029                 }
2030             }
2031         //}
2032     }
2033 
2034     return 0;
2035 } // wl_rx_dma
2036 /*============================================================================*/
2037 #endif  // ENABLE_DMA
2038