11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  smctr.c: A network driver for the SMC Token Ring Adapters.
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Written by Jay Schulist <jschlst@samba.org>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  This software may be used and distributed according to the terms
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  of the GNU General Public License, incorporated herein by reference.
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  This device driver works with the following SMC adapters:
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      - SMC TokenCard Elite   (8115T, chips 825/584)
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      - SMC TokenCard Elite/A MCA (8115T/A, chips 825/594)
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Source(s):
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  	- SMC TokenCard SDK.
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Maintainer(s):
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    JS        Jay Schulist <jschlst@samba.org>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Changes:
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    07102000          JS      Fixed a timing problem in smctr_wait_cmd();
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *                              Also added a bit more discriptive error msgs.
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    07122000          JS      Fixed problem with detecting a card with
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *				module io/irq/mem specified.
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  To do:
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *    1. Multicast support.
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
28113aa838ec3a235d883f8357d31d90e16c47fc89Alan Cox *  Initial 2.5 cleanup Alan Cox <alan@lxorguk.ukuu.org.uk>  2002/10/28
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/fcntl.h>
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ptrace.h>
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/ioport.h>
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/in.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/time.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mca-legacy.h>
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/netdevice.h>
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/etherdevice.h>
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h>
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/trdevice.h>
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bitops.h>
500f805b86c9492c294c710de8539a8be68b521a86David Woodhouse#include <linux/firmware.h>
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/dma.h>
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h>
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if BITS_PER_LONG == 64
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#error FIXME: driver does not support 64-bit platforms
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "smctr.h"               /* Our Stuff */
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
621770e430ca1361fb8143c328037d1a3f34391602Hannes Ederstatic const char version[] __initdata =
631770e430ca1361fb8143c328037d1a3f34391602Hannes Eder	KERN_INFO "smctr.c: v1.4 7/12/00 by jschlst@samba.org\n";
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char cardname[] = "smctr";
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMCTR_IO_EXTENT   20
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_MCA_LEGACY
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int smctr_posid = 0x6ec6;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int ringspeed;
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* SMC Name of the Adapter. */
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char smctr_name[] = "SMC TokenCard";
77de70b4c87b8f1d484cf533536c0c6ce2e05101cfAdrian Bunkstatic char *smctr_model = "Unknown";
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Use 0 for production, 1 for verification, 2 for debug, and
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3 for very verbose debug.
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifndef SMCTR_DEBUG
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define SMCTR_DEBUG 1
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int smctr_debug = SMCTR_DEBUG;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* smctr.c prototypes and functions are arranged alphabeticly
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for clearity, maintainability and pure old fashion fun.
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* A */
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_alloc_shared_memory(struct net_device *dev);
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* B */
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_bypass_state(struct net_device *dev);
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* C */
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_checksum_firmware(struct net_device *dev);
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init smctr_chk_isa(struct net_device *dev);
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_chg_rx_mask(struct net_device *dev);
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_clear_int(struct net_device *dev);
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_clear_trc_reset(int ioaddr);
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_close(struct net_device *dev);
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* D */
1050f805b86c9492c294c710de8539a8be68b521a86David Woodhousestatic int smctr_decode_firmware(struct net_device *dev,
1060f805b86c9492c294c710de8539a8be68b521a86David Woodhouse				 const struct firmware *fw);
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_disable_16bit(struct net_device *dev);
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_disable_adapter_ctrl_store(struct net_device *dev);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_disable_bic_int(struct net_device *dev);
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* E */
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_enable_16bit(struct net_device *dev);
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_enable_adapter_ctrl_store(struct net_device *dev);
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_enable_adapter_ram(struct net_device *dev);
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_enable_bic_int(struct net_device *dev);
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* G */
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init smctr_get_boardid(struct net_device *dev, int mca);
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_get_group_address(struct net_device *dev);
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_get_functional_address(struct net_device *dev);
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int smctr_get_num_rx_bdbs(struct net_device *dev);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_get_physical_drop_number(struct net_device *dev);
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic __u8 *smctr_get_rx_pointer(struct net_device *dev, short queue);
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_get_station_id(struct net_device *dev);
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue,
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 bytes_count);
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_get_upstream_neighbor_addr(struct net_device *dev);
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* H */
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_hardware_send_packet(struct net_device *dev,
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp);
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* I */
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_acbs(struct net_device *dev);
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_adapter(struct net_device *dev);
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_card_real(struct net_device *dev);
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_rx_bdbs(struct net_device *dev);
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_rx_fcbs(struct net_device *dev);
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_shared_memory(struct net_device *dev);
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_tx_bdbs(struct net_device *dev);
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_tx_fcbs(struct net_device *dev);
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_internal_self_test(struct net_device *dev);
1427d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t smctr_interrupt(int irq, void *dev_id);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_enable_int_cmd(struct net_device *dev,
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 interrupt_enable_mask);
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code,
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 ibits);
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_init_timers_cmd(struct net_device *dev);
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_init_txrx_cmd(struct net_device *dev);
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_insert_cmd(struct net_device *dev);
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_read_ring_status_cmd(struct net_device *dev);
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_read_word_cmd(struct net_device *dev, __u16 aword_cnt);
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_remove_cmd(struct net_device *dev);
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_resume_acb_cmd(struct net_device *dev);
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_resume_rx_bdb_cmd(struct net_device *dev, __u16 queue);
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_resume_rx_fcb_cmd(struct net_device *dev, __u16 queue);
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_resume_tx_fcb_cmd(struct net_device *dev, __u16 queue);
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_test_internal_rom_cmd(struct net_device *dev);
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_test_hic_cmd(struct net_device *dev);
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_test_mac_reg_cmd(struct net_device *dev);
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_trc_loopback_cmd(struct net_device *dev);
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_tri_loopback_cmd(struct net_device *dev);
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_write_byte_cmd(struct net_device *dev,
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        short aword_cnt, void *byte);
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_write_word_cmd(struct net_device *dev,
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        short aword_cnt, void *word);
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* J */
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_join_complete_state(struct net_device *dev);
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* L */
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_link_tx_fcbs_to_bdbs(struct net_device *dev);
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_load_firmware(struct net_device *dev);
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_load_node_addr(struct net_device *dev);
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_lobe_media_test(struct net_device *dev);
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_lobe_media_test_cmd(struct net_device *dev);
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_lobe_media_test_state(struct net_device *dev);
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* M */
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_8025_hdr(struct net_device *dev,
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_HEADER *rmf, MAC_HEADER *tmf, __u16 ac_fc);
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_access_pri(struct net_device *dev,
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv);
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_addr_mod(struct net_device *dev, MAC_SUB_VECTOR *tsv);
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_auth_funct_class(struct net_device *dev,
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv);
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_corr(struct net_device *dev,
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv, __u16 correlator);
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_funct_addr(struct net_device *dev,
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv);
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_group_addr(struct net_device *dev,
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv);
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_phy_drop_num(struct net_device *dev,
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv);
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_product_id(struct net_device *dev, MAC_SUB_VECTOR *tsv);
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_station_id(struct net_device *dev, MAC_SUB_VECTOR *tsv);
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_ring_station_status(struct net_device *dev,
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv);
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_ring_station_version(struct net_device *dev,
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv);
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_tx_status_code(struct net_device *dev,
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv, __u16 tx_fstatus);
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_upstream_neighbor_addr(struct net_device *dev,
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv);
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_wrap_data(struct net_device *dev,
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv);
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* O */
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_open(struct net_device *dev);
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_open_tr(struct net_device *dev);
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* P */
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct net_device *smctr_probe(int unit);
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init smctr_probe1(struct net_device *dev, int ioaddr);
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_device *dev, __u16 rx_status);
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* R */
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_ram_memory_test(struct net_device *dev);
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 *correlator);
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_rcv_init(struct net_device *dev, MAC_HEADER *rmf,
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 *correlator);
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_rcv_tx_forward(struct net_device *dev, MAC_HEADER *rmf);
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_rcv_rq_addr_state_attch(struct net_device *dev,
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_HEADER *rmf, __u16 *correlator);
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_rcv_unknown(struct net_device *dev, MAC_HEADER *rmf,
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 *correlator);
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_reset_adapter(struct net_device *dev);
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_restart_tx_chain(struct net_device *dev, short queue);
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_ring_status_chg(struct net_device *dev);
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_rx_frame(struct net_device *dev);
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* S */
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_dat(struct net_device *dev);
23561a84108547c1c017683f15311ccbede249fc6faStephen Hemmingerstatic netdev_tx_t smctr_send_packet(struct sk_buff *skb,
23661a84108547c1c017683f15311ccbede249fc6faStephen Hemminger					   struct net_device *dev);
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_lobe_media_test(struct net_device *dev);
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_rpt_addr(struct net_device *dev, MAC_HEADER *rmf,
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 correlator);
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_rpt_attch(struct net_device *dev, MAC_HEADER *rmf,
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 correlator);
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_rpt_state(struct net_device *dev, MAC_HEADER *rmf,
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 correlator);
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_rpt_tx_forward(struct net_device *dev,
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_HEADER *rmf, __u16 tx_fstatus);
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_rsp(struct net_device *dev, MAC_HEADER *rmf,
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 rcode, __u16 correlator);
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_rq_init(struct net_device *dev);
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 *tx_fstatus);
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_auth_access_pri(struct net_device *dev,
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv);
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_auth_funct_class(struct net_device *dev,
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv);
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_corr(struct net_device *dev, MAC_SUB_VECTOR *rsv,
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u16 *correlator);
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_error_timer_value(struct net_device *dev,
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv);
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_frame_forward(struct net_device *dev,
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv, __u8 dc_sc);
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_local_ring_num(struct net_device *dev,
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv);
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short smctr_set_ctrl_attention(struct net_device *dev);
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void smctr_set_multicast_list(struct net_device *dev);
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_page(struct net_device *dev, __u8 *buf);
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_phy_drop(struct net_device *dev,
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv);
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_ring_speed(struct net_device *dev);
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_rx_look_ahead(struct net_device *dev);
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_trc_reset(int ioaddr);
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_setup_single_cmd(struct net_device *dev,
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 command, __u16 subcommand);
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_setup_single_cmd_w_data(struct net_device *dev,
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 command, __u16 subcommand);
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *smctr_malloc(struct net_device *dev, __u16 size);
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_status_chg(struct net_device *dev);
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* T */
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void smctr_timeout(struct net_device *dev);
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_trc_send_packet(struct net_device *dev, FCBlock *fcb,
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 queue);
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic __u16 smctr_tx_complete(struct net_device *dev, __u16 queue);
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short smctr_tx_move_frame(struct net_device *dev,
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct sk_buff *skb, __u8 *pbuff, unsigned int bytes);
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* U */
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_update_err_stats(struct net_device *dev);
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_update_rx_chain(struct net_device *dev, __u16 queue);
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_update_tx_chain(struct net_device *dev, FCBlock *fcb,
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 queue);
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* W */
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_wait_cmd(struct net_device *dev);
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_wait_while_cbusy(struct net_device *dev);
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TO_256_BYTE_BOUNDRY(X)  (((X + 0xff) & 0xff00) - X)
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define TO_PARAGRAPH_BOUNDRY(X) (((X + 0x0f) & 0xfff0) - X)
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define PARAGRAPH_BOUNDRY(X)    smctr_malloc(dev, TO_PARAGRAPH_BOUNDRY(X))
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Allocate Adapter Shared Memory.
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * IMPORTANT NOTE: Any changes to this function MUST be mirrored in the
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * function "get_num_rx_bdbs" below!!!
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Order of memory allocation:
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       0. Initial System Configuration Block Pointer
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       1. System Configuration Block
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       2. System Control Block
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       3. Action Command Block
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       4. Interrupt Status Block
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       5. MAC TX FCB'S
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       6. NON-MAC TX FCB'S
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       7. MAC TX BDB'S
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       8. NON-MAC TX BDB'S
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *       9. MAC RX FCB'S
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      10. NON-MAC RX FCB'S
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      11. MAC RX BDB'S
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      12. NON-MAC RX BDB'S
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      13. MAC TX Data Buffer( 1, 256 byte buffer)
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      14. MAC RX Data Buffer( 1, 256 byte buffer)
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      15. NON-MAC TX Data Buffer
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *      16. NON-MAC RX Data Buffer
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_alloc_shared_memory(struct net_device *dev)
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_alloc_shared_memory\n", dev->name);
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate initial System Control Block pointer.
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * This pointer is located in the last page, last offset - 4.
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->iscpb_ptr = (ISCPBlock *)(tp->ram_access + ((__u32)64 * 0x400)
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                - (long)ISCP_BLOCK_SIZE);
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate System Control Blocks. */
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->scgb_ptr = (SCGBlock *)smctr_malloc(dev, sizeof(SCGBlock));
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        PARAGRAPH_BOUNDRY(tp->sh_mem_used);
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr = (SCLBlock *)smctr_malloc(dev, sizeof(SCLBlock));
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        PARAGRAPH_BOUNDRY(tp->sh_mem_used);
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->acb_head = (ACBlock *)smctr_malloc(dev,
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                sizeof(ACBlock)*tp->num_acbs);
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        PARAGRAPH_BOUNDRY(tp->sh_mem_used);
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->isb_ptr = (ISBlock *)smctr_malloc(dev, sizeof(ISBlock));
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        PARAGRAPH_BOUNDRY(tp->sh_mem_used);
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->misc_command_data = (__u16 *)smctr_malloc(dev, MISC_DATA_SIZE);
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        PARAGRAPH_BOUNDRY(tp->sh_mem_used);
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate transmit FCBs. */
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_fcb_head[MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                sizeof(FCBlock) * tp->num_tx_fcbs[MAC_QUEUE]);
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_fcb_head[NON_MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                sizeof(FCBlock) * tp->num_tx_fcbs[NON_MAC_QUEUE]);
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_fcb_head[BUG_QUEUE] = (FCBlock *)smctr_malloc(dev,
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                sizeof(FCBlock) * tp->num_tx_fcbs[BUG_QUEUE]);
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate transmit BDBs. */
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_bdb_head[MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                sizeof(BDBlock) * tp->num_tx_bdbs[MAC_QUEUE]);
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_bdb_head[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                sizeof(BDBlock) * tp->num_tx_bdbs[NON_MAC_QUEUE]);
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_bdb_head[BUG_QUEUE] = (BDBlock *)smctr_malloc(dev,
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                sizeof(BDBlock) * tp->num_tx_bdbs[BUG_QUEUE]);
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate receive FCBs. */
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_fcb_head[MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                sizeof(FCBlock) * tp->num_rx_fcbs[MAC_QUEUE]);
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_fcb_head[NON_MAC_QUEUE] = (FCBlock *)smctr_malloc(dev,
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                sizeof(FCBlock) * tp->num_rx_fcbs[NON_MAC_QUEUE]);
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate receive BDBs. */
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_bdb_head[MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                sizeof(BDBlock) * tp->num_rx_bdbs[MAC_QUEUE]);
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_bdb_end[MAC_QUEUE] = (BDBlock *)smctr_malloc(dev, 0);
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_bdb_head[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev,
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                sizeof(BDBlock) * tp->num_rx_bdbs[NON_MAC_QUEUE]);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_bdb_end[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev, 0);
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate MAC transmit buffers.
39525985edcedea6396277003854657b5f3cb31a628Lucas De Marchi         * MAC Tx Buffers doen't have to be on an ODD Boundary.
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
3971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_head[MAC_QUEUE]
3981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[MAC_QUEUE]);
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_curr[MAC_QUEUE] = tp->tx_buff_head[MAC_QUEUE];
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_end [MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate BUG transmit buffers. */
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_head[BUG_QUEUE]
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[BUG_QUEUE]);
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_curr[BUG_QUEUE] = tp->tx_buff_head[BUG_QUEUE];
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_end[BUG_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate MAC receive data buffers.
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * MAC Rx buffer doesn't have to be on a 256 byte boundary.
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_buff_head[MAC_QUEUE] = (__u16 *)smctr_malloc(dev,
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[MAC_QUEUE]);
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_buff_end[MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate Non-MAC transmit buffers.
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * ?? For maximum Netware performance, put Tx Buffers on
41725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi         * ODD Boundary and then restore malloc to Even Boundrys.
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_malloc(dev, 1L);
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_head[NON_MAC_QUEUE]
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[NON_MAC_QUEUE]);
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_curr[NON_MAC_QUEUE] = tp->tx_buff_head[NON_MAC_QUEUE];
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_end [NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_malloc(dev, 1L);
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate Non-MAC receive data buffers.
427af901ca181d92aac3a7dc265144a9081a86d8f39André Goddard Rosa         * To guarantee a minimum of 256 contiguous memory to
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * UM_Receive_Packet's lookahead pointer, before a page
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * change or ring end is encountered, place each rx buffer on
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * a 256 byte boundary.
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_malloc(dev, TO_256_BYTE_BOUNDRY(tp->sh_mem_used));
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_buff_head[NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev,
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[NON_MAC_QUEUE]);
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_buff_end[NON_MAC_QUEUE] = (__u16 *)smctr_malloc(dev, 0);
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
437807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Enter Bypass state. */
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_bypass_state(struct net_device *dev)
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(smctr_debug > 10)
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	printk(KERN_DEBUG "%s: smctr_bypass_state\n", dev->name);
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE, JS_BYPASS_STATE);
4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
450807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_checksum_firmware(struct net_device *dev)
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 i, checksum = 0;
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_checksum_firmware\n", dev->name);
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_enable_adapter_ctrl_store(dev);
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < CS_RAM_SIZE; i += 2)
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                checksum += *((__u16 *)(tp->ram_access + i));
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->microcode_version = *(__u16 *)(tp->ram_access
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                + CS_RAM_VERSION_OFFSET);
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->microcode_version >>= 8;
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_disable_adapter_ctrl_store(dev);
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(checksum)
473807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return checksum;
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
475807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init smctr_chk_mca(struct net_device *dev)
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_MCA_LEGACY
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_local *tp = netdev_priv(dev);
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int current_slot;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u8 r1, r2, r3, r4, r5;
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	current_slot = mca_find_unused_adapter(smctr_posid, 0);
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(current_slot == MCA_NOTFOUND)
487807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet		return -ENODEV;
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mca_set_adapter_name(current_slot, smctr_name);
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mca_mark_as_used(current_slot);
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp->slot_num = current_slot;
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r1 = mca_read_stored_pos(tp->slot_num, 2);
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r2 = mca_read_stored_pos(tp->slot_num, 3);
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(tp->slot_num)
4971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(CNFG_POS_CONTROL_REG, (__u8)((tp->slot_num - 1) | CNFG_SLOT_ENABLE_BIT));
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		outb(CNFG_POS_CONTROL_REG, (__u8)((tp->slot_num) | CNFG_SLOT_ENABLE_BIT));
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r1 = inb(CNFG_POS_REG1);
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r2 = inb(CNFG_POS_REG0);
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp->bic_type = BIC_594_CHIP;
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* IO */
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r2 = mca_read_stored_pos(tp->slot_num, 2);
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r2 &= 0xF0;
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->base_addr = ((__u16)r2 << 8) + (__u16)0x800;
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	request_region(dev->base_addr, SMCTR_IO_EXTENT, smctr_name);
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* IRQ */
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r5 = mca_read_stored_pos(tp->slot_num, 5);
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r5 &= 0xC;
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        switch(r5)
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            	case 0:
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev->irq = 3;
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds               		break;
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            	case 0x4:
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev->irq = 4;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds               		break;
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            	case 0x8:
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev->irq = 10;
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds               		break;
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            	default:
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev->irq = 15;
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds               		break;
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5331fb9df5d3069064c037c81c0ab8bf783ffa5e373Thomas Gleixner	if (request_irq(dev->irq, smctr_interrupt, IRQF_SHARED, smctr_name, dev)) {
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		release_region(dev->base_addr, SMCTR_IO_EXTENT);
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENODEV;
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get RAM base */
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r3 = mca_read_stored_pos(tp->slot_num, 3);
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp->ram_base = ((__u32)(r3 & 0x7) << 13) + 0x0C0000;
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (r3 & 0x8)
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tp->ram_base += 0x010000;
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (r3 & 0x80)
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tp->ram_base += 0xF00000;
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get Ram Size */
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r3 &= 0x30;
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r3 >>= 4;
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp->ram_usable = (__u16)CNFG_SIZE_8KB << r3;
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp->ram_size = (__u16)CNFG_SIZE_64KB;
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp->board_id |= TOKEN_MEDIA;
5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r4 = mca_read_stored_pos(tp->slot_num, 4);
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp->rom_base = ((__u32)(r4 & 0x7) << 13) + 0x0C0000;
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (r4 & 0x8)
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tp->rom_base += 0x010000;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get ROM size. */
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r4 >>= 4;
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (r4) {
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 0:
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tp->rom_size = CNFG_SIZE_8KB;
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 1:
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tp->rom_size = CNFG_SIZE_16KB;
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case 2:
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tp->rom_size = CNFG_SIZE_32KB;
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tp->rom_size = ROM_DISABLE;
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Get Media Type. */
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r5 = mca_read_stored_pos(tp->slot_num, 5);
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r5 &= CNFG_MEDIA_TYPE_MASK;
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(r5)
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (0):
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tp->media_type = MEDIA_STP_4;
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (1):
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tp->media_type = MEDIA_STP_16;
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		case (3):
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tp->media_type = MEDIA_UTP_16;
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			tp->media_type = MEDIA_UTP_4;
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp->media_menu = 14;
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	r2 = mca_read_stored_pos(tp->slot_num, 2);
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(!(r2 & 0x02))
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tp->mode_bits |= EARLY_TOKEN_REL;
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Disable slot */
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	outb(CNFG_POS_CONTROL_REG, 0);
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp->board_id = smctr_get_boardid(dev, 1);
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch(tp->board_id & 0xffff)
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case WD8115TA:
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        smctr_model = "8115T/A";
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case WD8115T:
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if(tp->extra_info & CHIP_REV_MASK)
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                smctr_model = "8115T rev XE";
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        else
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                smctr_model = "8115T rev XD";
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                default:
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        smctr_model = "Unknown";
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
624807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return 0;
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
626807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return -1;
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* CONFIG_MCA_LEGACY */
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_chg_rx_mask(struct net_device *dev)
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err = 0;
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_DEBUG "%s: smctr_chg_rx_mask\n", dev->name);
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_enable_16bit(dev);
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_page(dev, (__u8 *)tp->ram_access);
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->mode_bits & LOOPING_MODE_MASK)
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 |= RX_OWN_BIT;
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 &= ~RX_OWN_BIT;
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->receive_mask & PROMISCUOUS_MODE)
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 |= PROMISCUOUS_BIT;
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 &= ~PROMISCUOUS_BIT;
6501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->receive_mask & ACCEPT_ERR_PACKETS)
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 |= SAVBAD_BIT;
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 &= ~SAVBAD_BIT;
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->receive_mask & ACCEPT_ATT_MAC_FRAMES)
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 |= RXATMAC;
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 &= ~RXATMAC;
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->receive_mask & ACCEPT_MULTI_PROM)
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word1 |= MULTICAST_ADDRESS_BIT;
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word1 &= ~MULTICAST_ADDRESS_BIT;
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->receive_mask & ACCEPT_SOURCE_ROUTING_SPANNING)
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word1 |= SOURCE_ROUTING_SPANNING_BITS;
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(tp->receive_mask & ACCEPT_SOURCE_ROUTING)
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->config_word1 |= SOURCE_ROUTING_EXPLORER_BIT;
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->config_word1 &= ~SOURCE_ROUTING_SPANNING_BITS;
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_write_word_cmd(dev, RW_CONFIG_REGISTER_0,
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                &tp->config_word0)))
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
679807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_write_word_cmd(dev, RW_CONFIG_REGISTER_1,
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                &tp->config_word1)))
6841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
685807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_disable_16bit(dev);
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
690807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_clear_int(struct net_device *dev)
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb((tp->trc_mask | CSR_CLRTINT), dev->base_addr + CSR);
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
699807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_clear_trc_reset(int ioaddr)
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 r;
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r = inb(ioaddr + MSR);
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(~MSR_RST & r, ioaddr + MSR);
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
709807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
7131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The inverse routine to smctr_open().
7141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_close(struct net_device *dev)
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct sk_buff *skb;
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	netif_stop_queue(dev);
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp->cleanup = 1;
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Check to see if adapter is already in a closed state. */
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->status != OPEN)
727807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return 0;
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_enable_16bit(dev);
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_page(dev, (__u8 *)tp->ram_access);
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_remove_cmd(dev)))
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_disable_16bit(dev);
735807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(;;)
7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                skb = skb_dequeue(&tp->SendSkbQueue);
7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(skb == NULL)
7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
7431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->QueueSkb++;
7441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                dev_kfree_skb(skb);
7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
748807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7510f805b86c9492c294c710de8539a8be68b521a86David Woodhousestatic int smctr_decode_firmware(struct net_device *dev,
7520f805b86c9492c294c710de8539a8be68b521a86David Woodhouse				 const struct firmware *fw)
7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
7551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        short bit = 0x80, shift = 12;
7561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        DECODE_TREE_NODE *tree;
7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        short branch, tsize;
7581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 buff = 0;
7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        long weight;
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 *ucode;
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 *mem;
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_decode_firmware\n", dev->name);
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7660f805b86c9492c294c710de8539a8be68b521a86David Woodhouse        weight  = *(long *)(fw->data + WEIGHT_OFFSET);
7670f805b86c9492c294c710de8539a8be68b521a86David Woodhouse        tsize   = *(__u8 *)(fw->data + TREE_SIZE_OFFSET);
7680f805b86c9492c294c710de8539a8be68b521a86David Woodhouse        tree    = (DECODE_TREE_NODE *)(fw->data + TREE_OFFSET);
7690f805b86c9492c294c710de8539a8be68b521a86David Woodhouse        ucode   = (__u8 *)(fw->data + TREE_OFFSET
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        + (tsize * sizeof(DECODE_TREE_NODE)));
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem     = (__u16 *)(tp->ram_access);
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        while(weight)
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                branch = ROOT;
7761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                while((tree + branch)->tag != LEAF && weight)
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        branch = *ucode & bit ? (tree + branch)->llink
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                : (tree + branch)->rlink;
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bit >>= 1;
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        weight--;
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(bit == 0)
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        {
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                bit = 0x80;
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                ucode++;
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        }
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                buff |= (tree + branch)->info << shift;
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                shift -= 4;
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(shift < 0)
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        *(mem++) = SWAP_BYTES(buff);
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        buff    = 0;
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        shift   = 12;
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* The following assumes the Control Store Memory has
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * been initialized to zero. If the last partial word
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * is zero, it will not be written.
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(buff)
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *(mem++) = SWAP_BYTES(buff);
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
809807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_disable_16bit(struct net_device *dev)
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
814807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * On Exit, Adapter is:
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. TRC is in a reset state and un-initialized.
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. Adapter memory is enabled.
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3. Control Store memory is out of context (-WCSS is 1).
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_disable_adapter_ctrl_store(struct net_device *dev)
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ioaddr = dev->base_addr;
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_disable_adapter_ctrl_store\n", dev->name);
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->trc_mask |= CSR_WCSS;
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(tp->trc_mask, ioaddr + CSR);
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
834807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_disable_bic_int(struct net_device *dev)
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ioaddr = dev->base_addr;
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->trc_mask = CSR_MSK_ALL | CSR_MSKCBUSY
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	        | CSR_MSKTINT | CSR_WCSS;
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(tp->trc_mask, ioaddr + CSR);
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
846807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_enable_16bit(struct net_device *dev)
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8    r;
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->adapter_bus == BUS_ISA16_TYPE)
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                r = inb(dev->base_addr + LAAR);
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                outb((r | LAAR_MEM16ENB), dev->base_addr + LAAR);
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
860807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * To enable the adapter control store memory:
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. Adapter must be in a RESET state.
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. Adapter memory must be enabled.
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3. Control Store Memory is in context (-WCSS is 0).
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_enable_adapter_ctrl_store(struct net_device *dev)
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ioaddr = dev->base_addr;
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_enable_adapter_ctrl_store\n", dev->name);
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_trc_reset(ioaddr);
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_enable_adapter_ram(dev);
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->trc_mask &= ~CSR_WCSS;
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(tp->trc_mask, ioaddr + CSR);
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
883807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_enable_adapter_ram(struct net_device *dev)
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ioaddr = dev->base_addr;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 r;
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_enable_adapter_ram\n", dev->name);
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r = inb(ioaddr + MSR);
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(MSR_MEMB | r, ioaddr + MSR);
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
897807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_enable_bic_int(struct net_device *dev)
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ioaddr = dev->base_addr;
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 r;
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        switch(tp->bic_type)
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case (BIC_584_CHIP):
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->trc_mask = CSR_MSKCBUSY | CSR_WCSS;
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        outb(tp->trc_mask, ioaddr + CSR);
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        r = inb(ioaddr + IRR);
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        outb(r | IRR_IEN, ioaddr + IRR);
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case (BIC_594_CHIP):
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->trc_mask = CSR_MSKCBUSY | CSR_WCSS;
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        outb(tp->trc_mask, ioaddr + CSR);
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        r = inb(ioaddr + IMCCR);
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        outb(r | IMCCR_EIL, ioaddr + IMCCR);
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
923807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init smctr_chk_isa(struct net_device *dev)
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ioaddr = dev->base_addr;
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 r1, r2, b, chksum = 0;
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 r;
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err = -ENODEV;
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_chk_isa %#4x\n", dev->name, ioaddr);
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if((ioaddr & 0x1F) != 0)
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                goto out;
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Grab the region so that no one else tries to probe our ioports. */
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!request_region(ioaddr, SMCTR_IO_EXTENT, smctr_name)) {
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EBUSY;
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Checksum SMC node address */
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < 8; i++)
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                b = inb(ioaddr + LAR0 + i);
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                chksum += b;
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if (chksum != NODE_ADDR_CKSUM)
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                goto out2;
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        b = inb(ioaddr + BDID);
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(b != BRD_ID_8115T)
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_ERR "%s: The adapter found is not supported\n", dev->name);
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                goto out2;
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Check for 8115T Board ID */
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r2 = 0;
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(r = 0; r < 8; r++)
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            r1 = inb(ioaddr + 0x8 + r);
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds            r2 += r1;
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* value of RegF adds up the sum to 0xFF */
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((r2 != 0xFF) && (r2 != 0xEE))
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                goto out2;
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Get adapter ID */
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->board_id = smctr_get_boardid(dev, 0);
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        switch(tp->board_id & 0xffff)
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case WD8115TA:
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        smctr_model = "8115T/A";
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case WD8115T:
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if(tp->extra_info & CHIP_REV_MASK)
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                smctr_model = "8115T rev XE";
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        else
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                smctr_model = "8115T rev XD";
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                default:
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        smctr_model = "Unknown";
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Store BIC type. */
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->bic_type = BIC_584_CHIP;
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->nic_type = NIC_825_CHIP;
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Copy Ram Size */
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->ram_usable  = CNFG_SIZE_16KB;
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->ram_size    = CNFG_SIZE_64KB;
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Get 58x Ram Base */
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr);
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 &= 0x3F;
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r2 = inb(ioaddr + CNFG_LAAR_584);
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r2 &= CNFG_LAAR_MASK;
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r2 <<= 3;
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r2 |= ((r1 & 0x38) >> 3);
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->ram_base = ((__u32)r2 << 16) + (((__u32)(r1 & 0x7)) << 13);
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Get 584 Irq */
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = 0;
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + CNFG_ICR_583);
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 &= CNFG_ICR_IR2_584;
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r2 = inb(ioaddr + CNFG_IRR_583);
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r2 &= CNFG_IRR_IRQS;     /* 0x60 */
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r2 >>= 5;
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        switch(r2)
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case 0:
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(r1 == 0)
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                dev->irq = 2;
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        else
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                dev->irq = 10;
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case 1:
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(r1 == 0)
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                dev->irq = 3;
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        else
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                dev->irq = 11;
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case 2:
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(r1 == 0)
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        {
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(tp->extra_info & ALTERNATE_IRQ_BIT)
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        dev->irq = 5;
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                else
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        dev->irq = 4;
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        }
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        else
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                dev->irq = 15;
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case 3:
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(r1 == 0)
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                dev->irq = 7;
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        else
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                dev->irq = 4;
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                default:
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_ERR "%s: No IRQ found aborting\n", dev->name);
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        goto out2;
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         }
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10641fb9df5d3069064c037c81c0ab8bf783ffa5e373Thomas Gleixner        if (request_irq(dev->irq, smctr_interrupt, IRQF_SHARED, smctr_name, dev))
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                goto out2;
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Get 58x Rom Base */
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + CNFG_BIO_583);
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 &= 0x3E;
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 |= 0x40;
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rom_base = (__u32)r1 << 13;
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Get 58x Rom Size */
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + CNFG_BIO_583);
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 &= 0xC0;
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(r1 == 0)
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->rom_size = ROM_DISABLE;
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
10811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                r1 >>= 6;
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->rom_size = (__u16)CNFG_SIZE_8KB << r1;
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Get 58x Boot Status */
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + CNFG_GP2);
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->mode_bits &= (~BOOT_STATUS_MASK);
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(r1 & CNFG_GP2_BOOT_NIBBLE)
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->mode_bits |= BOOT_TYPE_1;
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Get 58x Zero Wait State */
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->mode_bits &= (~ZERO_WAIT_STATE_MASK);
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + CNFG_IRR_583);
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(r1 & CNFG_IRR_ZWS)
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 tp->mode_bits |= ZERO_WAIT_STATE_8_BIT;
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->board_id & BOARD_16BIT)
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                r1 = inb(ioaddr + CNFG_LAAR_584);
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(r1 & CNFG_LAAR_ZWS)
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->mode_bits |= ZERO_WAIT_STATE_16_BIT;
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Get 584 Media Menu */
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->media_menu = 14;
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + CNFG_IRR_583);
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->mode_bits &= 0xf8ff;       /* (~CNFG_INTERFACE_TYPE_MASK) */
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((tp->board_id & TOKEN_MEDIA) == TOKEN_MEDIA)
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Get Advanced Features */
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(((r1 & 0x6) >> 1) == 0x3)
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->media_type |= MEDIA_UTP_16;
11191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(((r1 & 0x6) >> 1) == 0x2)
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                tp->media_type |= MEDIA_STP_16;
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        else
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        {
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(((r1 & 0x6) >> 1) == 0x1)
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        tp->media_type |= MEDIA_UTP_4;
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                else
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        tp->media_type |= MEDIA_STP_4;
11301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        }
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                r1 = inb(ioaddr + CNFG_GP2);
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(!(r1 & 0x2) )           /* GP2_ETRD */
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->mode_bits |= EARLY_TOKEN_REL;
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* see if the chip is corrupted
11381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(smctr_read_584_chksum(ioaddr))
11391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
11401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_ERR "%s: EEPROM Checksum Failure\n", dev->name);
11411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			free_irq(dev->irq, dev);
11421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        goto out2;
11431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
11441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*/
11451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
11461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1147807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout2:
11501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	release_region(ioaddr, SMCTR_IO_EXTENT);
11511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
11521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
11531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init smctr_get_boardid(struct net_device *dev, int mca)
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
11581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ioaddr = dev->base_addr;
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 r, r1, IdByte;
11601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 BoardIdMask;
11611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->board_id = BoardIdMask = 0;
11631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(mca)
11651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
11661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		BoardIdMask |= (MICROCHANNEL+INTERFACE_CHIP+TOKEN_MEDIA+PAGED_RAM+BOARD_16BIT);
11671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tp->extra_info |= (INTERFACE_594_CHIP+RAM_SIZE_64K+NIC_825_BIT+ALTERNATE_IRQ_BIT+SLOT_16BIT);
11681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
11701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
11711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	BoardIdMask|=(INTERFACE_CHIP+TOKEN_MEDIA+PAGED_RAM+BOARD_16BIT);
11721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	tp->extra_info |= (INTERFACE_584_CHIP + RAM_SIZE_64K
11731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	        + NIC_825_BIT + ALTERNATE_IRQ_BIT);
11741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(!mca)
11771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
11781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	r = inb(ioaddr + BID_REG_1);
11791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	r &= 0x0c;
11801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       		outb(r, ioaddr + BID_REG_1);
11811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	r = inb(ioaddr + BID_REG_1);
11821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	if(r & BID_SIXTEEN_BIT_BIT)
11841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	{
11851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	        tp->extra_info |= SLOT_16BIT;
11861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	        tp->adapter_bus = BUS_ISA16_TYPE;
11871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	}
11881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	else
11891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	        tp->adapter_bus = BUS_ISA8_TYPE;
11901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
11911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
11921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tp->adapter_bus = BUS_MCA_TYPE;
11931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Get Board Id Byte */
11951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        IdByte = inb(ioaddr + BID_BOARD_ID_BYTE);
11961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* if Major version > 1.0 then
11981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         *      return;
11991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
12001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(IdByte & 0xF8)
1201807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -1;
12021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + BID_REG_1);
12041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 &= BID_ICR_MASK;
12051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 |= BID_OTHER_BIT;
12061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(r1, ioaddr + BID_REG_1);
12081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + BID_REG_3);
12091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 &= BID_EAR_MASK;
12111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 |= BID_ENGR_PAGE;
12121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(r1, ioaddr + BID_REG_3);
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + BID_REG_1);
12151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 &= BID_ICR_MASK;
12161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 |= (BID_RLA | BID_OTHER_BIT);
12171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(r1, ioaddr + BID_REG_1);
12191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + BID_REG_1);
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        while(r1 & BID_RECALL_DONE_MASK)
12221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                r1 = inb(ioaddr + BID_REG_1);
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r = inb(ioaddr + BID_LAR_0 + BID_REG_6);
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* clear chip rev bits */
12271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->extra_info &= ~CHIP_REV_MASK;
12281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->extra_info |= ((r & BID_EEPROM_CHIP_REV_MASK) << 6);
12291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + BID_REG_1);
12311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 &= BID_ICR_MASK;
12321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 |= BID_OTHER_BIT;
12331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(r1, ioaddr + BID_REG_1);
12351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + BID_REG_3);
12361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 &= BID_EAR_MASK;
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 |= BID_EA6;
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(r1, ioaddr + BID_REG_3);
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + BID_REG_1);
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 &= BID_ICR_MASK;
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 |= BID_RLA;
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(r1, ioaddr + BID_REG_1);
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r1 = inb(ioaddr + BID_REG_1);
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        while(r1 & BID_RECALL_DONE_MASK)
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                r1 = inb(ioaddr + BID_REG_1);
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1252807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return BoardIdMask;
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_get_group_address(struct net_device *dev)
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_issue_read_word_cmd(dev, RW_INDIVIDUAL_GROUP_ADDR);
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1259807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return smctr_wait_cmd(dev);
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_get_functional_address(struct net_device *dev)
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_issue_read_word_cmd(dev, RW_FUNCTIONAL_ADDR);
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1266807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return smctr_wait_cmd(dev);
12671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Calculate number of Non-MAC receive BDB's and data buffers.
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function must simulate allocateing shared memory exactly
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as the allocate_shared_memory function above.
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned int smctr_get_num_rx_bdbs(struct net_device *dev)
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int mem_used = 0;
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate System Control Blocks. */
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += sizeof(SCGBlock);
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += sizeof(SCLBlock);
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += sizeof(ACBlock) * tp->num_acbs;
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += sizeof(ISBlock);
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += MISC_DATA_SIZE;
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate transmit FCB's. */
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += TO_PARAGRAPH_BOUNDRY(mem_used);
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += sizeof(FCBlock) * tp->num_tx_fcbs[MAC_QUEUE];
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += sizeof(FCBlock) * tp->num_tx_fcbs[NON_MAC_QUEUE];
12981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += sizeof(FCBlock) * tp->num_tx_fcbs[BUG_QUEUE];
12991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate transmit BDBs. */
13011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += sizeof(BDBlock) * tp->num_tx_bdbs[MAC_QUEUE];
13021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += sizeof(BDBlock) * tp->num_tx_bdbs[NON_MAC_QUEUE];
13031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += sizeof(BDBlock) * tp->num_tx_bdbs[BUG_QUEUE];
13041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate receive FCBs. */
13061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += sizeof(FCBlock) * tp->num_rx_fcbs[MAC_QUEUE];
13071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += sizeof(FCBlock) * tp->num_rx_fcbs[NON_MAC_QUEUE];
13081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate receive BDBs. */
13101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += sizeof(BDBlock) * tp->num_rx_bdbs[MAC_QUEUE];
13111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate MAC transmit buffers.
131325985edcedea6396277003854657b5f3cb31a628Lucas De Marchi         * MAC transmit buffers don't have to be on an ODD Boundary.
13141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
13151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += tp->tx_buff_size[MAC_QUEUE];
13161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate BUG transmit buffers. */
13181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += tp->tx_buff_size[BUG_QUEUE];
13191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate MAC receive data buffers.
13211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * MAC receive buffers don't have to be on a 256 byte boundary.
13221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
13231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += RX_DATA_BUFFER_SIZE * tp->num_rx_bdbs[MAC_QUEUE];
13241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate Non-MAC transmit buffers.
13261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * For maximum Netware performance, put Tx Buffers on
132725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi         * ODD Boundary,and then restore malloc to Even Boundrys.
13281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
13291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += 1L;
13301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += tp->tx_buff_size[NON_MAC_QUEUE];
13311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += 1L;
13321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* CALCULATE NUMBER OF NON-MAC RX BDB'S
13341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * AND NON-MAC RX DATA BUFFERS
13351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         *
13361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * Make sure the mem_used offset at this point is the
13371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * same as in allocate_shared memory or the following
13381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * boundary adjustment will be incorrect (i.e. not allocating
13391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * the non-mac receive buffers above cannot change the 256
13401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * byte offset).
13411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         *
13421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * Since this cannot be guaranteed, adding the full 256 bytes
13431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * to the amount of shared memory used at this point will guaranteed
13441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * that the rx data buffers do not overflow shared memory.
13451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
13461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mem_used += 0x100;
13471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1348807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return (0xffff - mem_used) / (RX_DATA_BUFFER_SIZE + sizeof(BDBlock));
13491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_get_physical_drop_number(struct net_device *dev)
13521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_issue_read_word_cmd(dev, RW_PHYSICAL_DROP_NUMBER);
13541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1355807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return smctr_wait_cmd(dev);
13561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic __u8 * smctr_get_rx_pointer(struct net_device *dev, short queue)
13591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
13611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        BDBlock *bdb;
13621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        bdb = (BDBlock *)((__u32)tp->ram_access
13641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                + (__u32)(tp->rx_fcb_curr[queue]->trc_bdb_ptr));
13651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_fcb_curr[queue]->bdb_ptr = bdb;
13671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1368807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return (__u8 *)bdb->data_block_ptr;
13691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_get_station_id(struct net_device *dev)
13721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_issue_read_word_cmd(dev, RW_INDIVIDUAL_MAC_ADDRESS);
13741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1375807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return smctr_wait_cmd(dev);
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Get the current statistics. This may be called with the card open
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * or closed.
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_device_stats *smctr_get_stats(struct net_device *dev)
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1386807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return (struct net_device_stats *)&tp->MacStat;
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic FCBlock *smctr_get_tx_fcb(struct net_device *dev, __u16 queue,
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 bytes_count)
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *pFCB;
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        BDBlock *pbdb;
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned short alloc_size;
13961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned short *temp;
13971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 20)
13991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "smctr_get_tx_fcb\n");
14001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* check if there is enough FCB blocks */
14021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->num_tx_fcbs_used[queue] >= tp->num_tx_fcbs[queue])
1403807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return (FCBlock *)(-1L);
14041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* round off the input pkt size to the nearest even number */
14061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        alloc_size = (bytes_count + 1) & 0xfffe;
14071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* check if enough mem */
14091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((tp->tx_buff_used[queue] + alloc_size) > tp->tx_buff_size[queue])
1410807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return (FCBlock *)(-1L);
14111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* check if past the end ;
14131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * if exactly enough mem to end of ring, alloc from front.
14141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * this avoids update of curr when curr = end
14151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
14161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(((unsigned long)(tp->tx_buff_curr[queue]) + alloc_size)
14171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                >= (unsigned long)(tp->tx_buff_end[queue]))
14181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
14191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* check if enough memory from ring head */
14201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                alloc_size = alloc_size +
14211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        (__u16)((__u32)tp->tx_buff_end[queue]
14221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        - (__u32)tp->tx_buff_curr[queue]);
14231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if((tp->tx_buff_used[queue] + alloc_size)
14251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        > tp->tx_buff_size[queue])
14261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
1427807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                        return (FCBlock *)(-1L);
14281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
14291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* ring wrap */
14311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->tx_buff_curr[queue] = tp->tx_buff_head[queue];
14321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
14331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_used[queue] += alloc_size;
14351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_tx_fcbs_used[queue]++;
14361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_fcb_curr[queue]->frame_length = bytes_count;
14371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_fcb_curr[queue]->memory_alloc = alloc_size;
14381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        temp = tp->tx_buff_curr[queue];
14391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_curr[queue]
14401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                = (__u16 *)((__u32)temp + (__u32)((bytes_count + 1) & 0xfffe));
14411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        pbdb = tp->tx_fcb_curr[queue]->bdb_ptr;
14431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        pbdb->buffer_length = bytes_count;
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        pbdb->data_block_ptr = temp;
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        pbdb->trc_data_block_ptr = TRC_POINTER(temp);
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        pFCB = tp->tx_fcb_curr[queue];
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_fcb_curr[queue] = tp->tx_fcb_curr[queue]->next_ptr;
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1450807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return pFCB;
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_get_upstream_neighbor_addr(struct net_device *dev)
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_issue_read_word_cmd(dev, RW_UPSTREAM_NEIGHBOR_ADDRESS);
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1457807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return smctr_wait_cmd(dev);
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_hardware_send_packet(struct net_device *dev,
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp)
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct tr_statistics *tstat = &tp->MacStat;
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct sk_buff *skb;
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG"%s: smctr_hardware_send_packet\n", dev->name);
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->status != OPEN)
1471807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -1;
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->monitor_state_ready != 1)
1474807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -1;
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(;;)
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Send first buffer from queue */
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                skb = skb_dequeue(&tp->SendSkbQueue);
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(skb == NULL)
1481807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                        return -1;
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->QueueSkb++;
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1485807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                if(skb->len < SMC_HEADER_SIZE || skb->len > tp->max_packet_size)
1486807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet			return -1;
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_enable_16bit(dev);
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_set_page(dev, (__u8 *)tp->ram_access);
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if((fcb = smctr_get_tx_fcb(dev, NON_MAC_QUEUE, skb->len))
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        == (FCBlock *)(-1L))
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        smctr_disable_16bit(dev);
1495807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                        return -1;
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_tx_move_frame(dev, skb,
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        (__u8 *)fcb->bdb_ptr->data_block_ptr, skb->len);
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_set_page(dev, (__u8 *)fcb);
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_trc_send_packet(dev, fcb, NON_MAC_QUEUE);
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                dev_kfree_skb(skb);
15051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tstat->tx_packets++;
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_disable_16bit(dev);
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1511807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_acbs(struct net_device *dev)
15151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
15171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i;
15181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        ACBlock *acb;
15191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
15211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_init_acbs\n", dev->name);
15221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        acb                     = tp->acb_head;
15241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        acb->cmd_done_status    = (ACB_COMMAND_DONE | ACB_COMMAND_SUCCESSFUL);
15251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        acb->cmd_info           = ACB_CHAIN_END;
15261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        acb->cmd                = 0;
15271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        acb->subcmd             = 0;
15281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        acb->data_offset_lo     = 0;
15291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        acb->data_offset_hi     = 0;
15301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        acb->next_ptr
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                = (ACBlock *)(((char *)acb) + sizeof(ACBlock));
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        acb->trc_next_ptr       = TRC_POINTER(acb->next_ptr);
15331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 1; i < tp->num_acbs; i++)
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                acb             = acb->next_ptr;
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                acb->cmd_done_status
15381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        = (ACB_COMMAND_DONE | ACB_COMMAND_SUCCESSFUL);
15391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                acb->cmd_info = ACB_CHAIN_END;
15401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                acb->cmd        = 0;
15411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                acb->subcmd     = 0;
15421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                acb->data_offset_lo = 0;
15431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                acb->data_offset_hi = 0;
15441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                acb->next_ptr
15451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        = (ACBlock *)(((char *)acb) + sizeof(ACBlock));
15461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                acb->trc_next_ptr = TRC_POINTER(acb->next_ptr);
15471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
15481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        acb->next_ptr           = tp->acb_head;
15501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        acb->trc_next_ptr       = TRC_POINTER(tp->acb_head);
15511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->acb_next            = tp->acb_head->next_ptr;
15521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->acb_curr            = tp->acb_head->next_ptr;
15531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_acbs_used       = 0;
15541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1555807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
15561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_adapter(struct net_device *dev)
15591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
15611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
15621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_init_adapter\n", dev->name);
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->status              = CLOSED;
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->page_offset_mask    = (tp->ram_usable * 1024) - 1;
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        skb_queue_head_init(&tp->SendSkbQueue);
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->QueueSkb = MAX_TX_QUEUE;
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(!(tp->group_address_0 & 0x0080))
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->group_address_0 |= 0x00C0;
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(!(tp->functional_address_0 & 0x00C0))
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->functional_address_0 |= 0x00C0;
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->functional_address[0] &= 0xFF7F;
15781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->authorized_function_classes == 0)
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->authorized_function_classes = 0x7FFF;
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->authorized_access_priority == 0)
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->authorized_access_priority = 0x06;
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_disable_bic_int(dev);
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_trc_reset(dev->base_addr);
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_enable_16bit(dev);
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_page(dev, (__u8 *)tp->ram_access);
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_checksum_firmware(dev))
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
1593807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                printk(KERN_ERR "%s: Previously loaded firmware is missing\n",dev->name);
1594807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet		return -ENOENT;
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_ram_memory_test(dev)))
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_ERR "%s: RAM memory test failed.\n", dev->name);
1600807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -EIO;
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	smctr_set_rx_look_ahead(dev);
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_load_node_addr(dev);
16051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize adapter for Internal Self Test. */
16071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_reset_adapter(dev);
16081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_init_card_real(dev)))
16091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
16101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_ERR "%s: Initialization of card failed (%d)\n",
16111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        dev->name, err);
1612807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -EINVAL;
16131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
16141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* This routine clobbers the TRC's internal registers. */
16161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_internal_self_test(dev)))
16171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
16181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_ERR "%s: Card failed internal self test (%d)\n",
16191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        dev->name, err);
1620807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -EINVAL;
16211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
16221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Re-Initialize adapter's internal registers */
16241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_reset_adapter(dev);
16251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_init_card_real(dev)))
16261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
16271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_ERR "%s: Initialization of card failed (%d)\n",
16281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        dev->name, err);
1629807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -EINVAL;
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_enable_bic_int(dev);
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_enable_int_cmd(dev, TRC_INTERRUPT_ENABLE_MASK)))
1635807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_disable_16bit(dev);
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1639807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_card_real(struct net_device *dev)
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err = 0;
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
16481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_init_card_real\n", dev->name);
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sh_mem_used = 0;
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_acbs    = NUM_OF_ACBS;
16521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Range Check Max Packet Size */
16541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->max_packet_size < 256)
16551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->max_packet_size = 256;
16561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
16571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
16581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(tp->max_packet_size > NON_MAC_TX_BUFFER_MEMORY)
16591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->max_packet_size = NON_MAC_TX_BUFFER_MEMORY;
16601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_of_tx_buffs = (NON_MAC_TX_BUFFER_MEMORY
16631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                / tp->max_packet_size) - 1;
16641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->num_of_tx_buffs > NUM_NON_MAC_TX_FCBS)
16661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->num_of_tx_buffs = NUM_NON_MAC_TX_FCBS;
16671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
16681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
16691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(tp->num_of_tx_buffs == 0)
16701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->num_of_tx_buffs = 1;
16711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
16721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Tx queue constants */
16741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_tx_fcbs        [BUG_QUEUE]     = NUM_BUG_TX_FCBS;
16751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_tx_bdbs        [BUG_QUEUE]     = NUM_BUG_TX_BDBS;
16761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_size       [BUG_QUEUE]     = BUG_TX_BUFFER_MEMORY;
16771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_used       [BUG_QUEUE]     = 0;
16781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_queue_status    [BUG_QUEUE]     = NOT_TRANSMITING;
16791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_tx_fcbs        [MAC_QUEUE]     = NUM_MAC_TX_FCBS;
16811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_tx_bdbs        [MAC_QUEUE]     = NUM_MAC_TX_BDBS;
16821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_size       [MAC_QUEUE]     = MAC_TX_BUFFER_MEMORY;
16831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_used       [MAC_QUEUE]     = 0;
16841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_queue_status    [MAC_QUEUE]     = NOT_TRANSMITING;
16851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_tx_fcbs        [NON_MAC_QUEUE] = NUM_NON_MAC_TX_FCBS;
16871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_tx_bdbs        [NON_MAC_QUEUE] = NUM_NON_MAC_TX_BDBS;
16881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_size       [NON_MAC_QUEUE] = NON_MAC_TX_BUFFER_MEMORY;
16891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_buff_used       [NON_MAC_QUEUE] = 0;
16901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_queue_status    [NON_MAC_QUEUE] = NOT_TRANSMITING;
16911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Receive Queue Constants */
16931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_rx_fcbs[MAC_QUEUE] = NUM_MAC_RX_FCBS;
16941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_rx_bdbs[MAC_QUEUE] = NUM_MAC_RX_BDBS;
16951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->extra_info & CHIP_REV_MASK)
16971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->num_rx_fcbs[NON_MAC_QUEUE] = 78;    /* 825 Rev. XE */
16981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
16991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->num_rx_fcbs[NON_MAC_QUEUE] = 7;     /* 825 Rev. XD */
17001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_rx_bdbs[NON_MAC_QUEUE] = smctr_get_num_rx_bdbs(dev);
17021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_alloc_shared_memory(dev);
17041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_init_shared_memory(dev);
17051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_init_timers_cmd(dev)))
1707807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
17081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_init_txrx_cmd(dev)))
17101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
17111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_ERR "%s: Hardware failure\n", dev->name);
1712807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
17131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
17141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1715807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
17161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_rx_bdbs(struct net_device *dev)
17191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
17211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i, j;
17221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        BDBlock *bdb;
17231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 *buf;
17241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
17261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_init_rx_bdbs\n", dev->name);
17271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < NUM_RX_QS_USED; i++)
17291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
17301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb = tp->rx_bdb_head[i];
17311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                buf = tp->rx_buff_head[i];
17321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb->info = (BDB_CHAIN_END | BDB_NO_WARNING);
17331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb->buffer_length = RX_DATA_BUFFER_SIZE;
17341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb->next_ptr = (BDBlock *)(((char *)bdb) + sizeof(BDBlock));
17351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb->data_block_ptr = buf;
17361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
17371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(i == NON_MAC_QUEUE)
17391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb->trc_data_block_ptr = RX_BUFF_TRC_POINTER(buf);
17401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
17411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb->trc_data_block_ptr = TRC_POINTER(buf);
17421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for(j = 1; j < tp->num_rx_bdbs[i]; j++)
17441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
17451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb->next_ptr->back_ptr = bdb;
17461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb = bdb->next_ptr;
17471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        buf = (__u16 *)((char *)buf + RX_DATA_BUFFER_SIZE);
17481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb->info = (BDB_NOT_CHAIN_END | BDB_NO_WARNING);
17491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb->buffer_length = RX_DATA_BUFFER_SIZE;
17501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb->next_ptr = (BDBlock *)(((char *)bdb) + sizeof(BDBlock));
17511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb->data_block_ptr = buf;
17521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
17531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(i == NON_MAC_QUEUE)
17551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                bdb->trc_data_block_ptr = RX_BUFF_TRC_POINTER(buf);
17561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        else
17571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                bdb->trc_data_block_ptr = TRC_POINTER(buf);
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
17591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb->next_ptr           = tp->rx_bdb_head[i];
17611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb->trc_next_ptr       = TRC_POINTER(tp->rx_bdb_head[i]);
17621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->rx_bdb_head[i]->back_ptr    = bdb;
17641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->rx_bdb_curr[i]              = tp->rx_bdb_head[i]->next_ptr;
17651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
17661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1767807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
17681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
17691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_rx_fcbs(struct net_device *dev)
17711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
17721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
17731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i, j;
17741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
17751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < NUM_RX_QS_USED; i++)
17771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
17781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb               = tp->rx_fcb_head[i];
17791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->frame_status = 0;
17801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->frame_length = 0;
17811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->info         = FCB_CHAIN_END;
17821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->next_ptr     = (FCBlock *)(((char*)fcb) + sizeof(FCBlock));
17831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(i == NON_MAC_QUEUE)
17841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->trc_next_ptr = RX_FCB_TRC_POINTER(fcb->next_ptr);
17851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
17861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
17871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for(j = 1; j < tp->num_rx_fcbs[i]; j++)
17891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
17901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->next_ptr->back_ptr = fcb;
17911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb                     = fcb->next_ptr;
17921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->frame_status       = 0;
17931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->frame_length       = 0;
17941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->info               = FCB_WARNING;
17951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->next_ptr
17961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                = (FCBlock *)(((char *)fcb) + sizeof(FCBlock));
17971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(i == NON_MAC_QUEUE)
17991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                fcb->trc_next_ptr
18001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        = RX_FCB_TRC_POINTER(fcb->next_ptr);
18011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        else
18021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                fcb->trc_next_ptr
18031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        = TRC_POINTER(fcb->next_ptr);
18041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
18051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->next_ptr = tp->rx_fcb_head[i];
18071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(i == NON_MAC_QUEUE)
18091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->trc_next_ptr = RX_FCB_TRC_POINTER(fcb->next_ptr);
18101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
18111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
18121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->rx_fcb_head[i]->back_ptr    = fcb;
18141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->rx_fcb_curr[i]              = tp->rx_fcb_head[i]->next_ptr;
18151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
18161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1817807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
18181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_shared_memory(struct net_device *dev)
18211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
18231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i;
18241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u32 *iscpb;
18251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
18271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_init_shared_memory\n", dev->name);
18281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_page(dev, (__u8 *)(unsigned int)tp->iscpb_ptr);
18301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize Initial System Configuration Point. (ISCP) */
18321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        iscpb = (__u32 *)PAGE_POINTER(&tp->iscpb_ptr->trc_scgb_ptr);
18331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *iscpb = (__u32)(SWAP_WORDS(TRC_POINTER(tp->scgb_ptr)));
18341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_page(dev, (__u8 *)tp->ram_access);
18361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize System Configuration Pointers. (SCP) */
18381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->scgb_ptr->config = (SCGB_ADDRESS_POINTER_FORMAT
18391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                | SCGB_MULTI_WORD_CONTROL | SCGB_DATA_FORMAT
18401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                | SCGB_BURST_LENGTH);
18411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->scgb_ptr->trc_sclb_ptr      = TRC_POINTER(tp->sclb_ptr);
18431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->scgb_ptr->trc_acb_ptr       = TRC_POINTER(tp->acb_head);
18441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->scgb_ptr->trc_isb_ptr       = TRC_POINTER(tp->isb_ptr);
18451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->scgb_ptr->isbsiz            = (sizeof(ISBlock)) - 2;
18461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize System Control Block. (SCB) */
18481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->valid_command    = SCLB_VALID | SCLB_CMD_NOP;
18491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->iack_code        = 0;
18501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->resume_control   = 0;
18511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->int_mask_control = 0;
18521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->int_mask_state   = 0;
18531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize Interrupt Status Block. (ISB) */
18551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < NUM_OF_INTERRUPTS; i++)
18561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
18571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->isb_ptr->IStatus[i].IType = 0xf0;
18581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->isb_ptr->IStatus[i].ISubtype = 0;
18591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
18601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->current_isb_index = 0;
18621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize Action Command Block. (ACB) */
18641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_init_acbs(dev);
18651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize transmit FCB's and BDB's. */
18671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_link_tx_fcbs_to_bdbs(dev);
18681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_init_tx_bdbs(dev);
18691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_init_tx_fcbs(dev);
18701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize receive FCB's and BDB's. */
18721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_init_rx_bdbs(dev);
18731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_init_rx_fcbs(dev);
18741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1875807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
18761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
18771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_tx_bdbs(struct net_device *dev)
18791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
18801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
18811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i, j;
18821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        BDBlock *bdb;
18831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < NUM_TX_QS_USED; i++)
18851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
18861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb = tp->tx_bdb_head[i];
18871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb->info = (BDB_NOT_CHAIN_END | BDB_NO_WARNING);
18881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb->next_ptr = (BDBlock *)(((char *)bdb) + sizeof(BDBlock));
18891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
18901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
18911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for(j = 1; j < tp->num_tx_bdbs[i]; j++)
18921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
18931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb->next_ptr->back_ptr = bdb;
18941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb = bdb->next_ptr;
18951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb->info = (BDB_NOT_CHAIN_END | BDB_NO_WARNING);
18961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb->next_ptr
18971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                = (BDBlock *)(((char *)bdb) + sizeof( BDBlock));                        bdb->trc_next_ptr = TRC_POINTER(bdb->next_ptr);
18981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
18991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb->next_ptr = tp->tx_bdb_head[i];
19011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb->trc_next_ptr = TRC_POINTER(tp->tx_bdb_head[i]);
19021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->tx_bdb_head[i]->back_ptr = bdb;
19031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
19041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1905807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
19061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_init_tx_fcbs(struct net_device *dev)
19091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
19111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i, j;
19121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
19131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < NUM_TX_QS_USED; i++)
19151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
19161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb               = tp->tx_fcb_head[i];
19171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->frame_status = 0;
19181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->frame_length = 0;
19191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->info         = FCB_CHAIN_END;
19201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->next_ptr = (FCBlock *)(((char *)fcb) + sizeof(FCBlock));
19211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
19221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for(j = 1; j < tp->num_tx_fcbs[i]; j++)
19241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
19251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->next_ptr->back_ptr = fcb;
19261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb                     = fcb->next_ptr;
19271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->frame_status       = 0;
19281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->frame_length       = 0;
19291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->info               = FCB_CHAIN_END;
19301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->next_ptr
19311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                = (FCBlock *)(((char *)fcb) + sizeof(FCBlock));
19321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->trc_next_ptr = TRC_POINTER(fcb->next_ptr);
19331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
19341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->next_ptr           = tp->tx_fcb_head[i];
19361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->trc_next_ptr       = TRC_POINTER(tp->tx_fcb_head[i]);
19371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->tx_fcb_head[i]->back_ptr    = fcb;
19391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->tx_fcb_end[i]               = tp->tx_fcb_head[i]->next_ptr;
19401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->tx_fcb_curr[i]              = tp->tx_fcb_head[i]->next_ptr;
19411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->num_tx_fcbs_used[i]         = 0;
19421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
19431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1944807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
19451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_internal_self_test(struct net_device *dev)
19481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
19501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
19511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_test_internal_rom_cmd(dev)))
1953807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
19541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_cmd(dev)))
1956807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
19571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->acb_head->cmd_done_status & 0xff)
1959807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -1;
19601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_test_hic_cmd(dev)))
1962807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
19631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_cmd(dev)))
1965807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
19661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->acb_head->cmd_done_status & 0xff)
1968807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -1;
19691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_test_mac_reg_cmd(dev)))
1971807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
19721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_cmd(dev)))
1974807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
19751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->acb_head->cmd_done_status & 0xff)
1977807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -1;
19781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1979807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
19801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
19811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
19831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The typical workload of the driver: Handle the network interface interrupts.
19841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
19857d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellsstatic irqreturn_t smctr_interrupt(int irq, void *dev_id)
19861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
19871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_device *dev = dev_id;
19881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp;
19891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ioaddr;
19901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 interrupt_unmask_bits = 0, interrupt_ack_code = 0xff00;
19911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 err1, err = NOT_MY_INTERRUPT;
19921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 isb_type, isb_subtype;
19931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 isb_index;
19941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        ioaddr = dev->base_addr;
19961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp = netdev_priv(dev);
19971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->status == NOT_INITIALIZED)
19991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                return IRQ_NONE;
20001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        spin_lock(&tp->lock);
20021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_disable_bic_int(dev);
20041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_enable_16bit(dev);
20051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_clear_int(dev);
20071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* First read the LSB */
20091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        while((tp->isb_ptr->IStatus[tp->current_isb_index].IType & 0xf0) == 0)
20101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
20111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                isb_index       = tp->current_isb_index;
20121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                isb_type        = tp->isb_ptr->IStatus[isb_index].IType;
20131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                isb_subtype     = tp->isb_ptr->IStatus[isb_index].ISubtype;
20141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                (tp->current_isb_index)++;
20161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(tp->current_isb_index == NUM_OF_INTERRUPTS)
20171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->current_isb_index = 0;
20181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(isb_type >= 0x10)
20201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
20211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        smctr_disable_16bit(dev);
20221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		        spin_unlock(&tp->lock);
20231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        return IRQ_HANDLED;
20241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
20251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                err = HARDWARE_FAILED;
20271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                interrupt_ack_code = isb_index;
20281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->isb_ptr->IStatus[isb_index].IType |= 0xf0;
20291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                interrupt_unmask_bits |= (1 << (__u16)isb_type);
20311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                switch(isb_type)
20331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
20341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ISB_IMC_MAC_TYPE_3:
20351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                smctr_disable_16bit(dev);
20361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                switch(isb_subtype)
20381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
20391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 0:
20401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->monitor_state = MS_MONITOR_FSM_INACTIVE;
20411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                               break;
20421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 1:
20441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->monitor_state = MS_REPEAT_BEACON_STATE;
20451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
20461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 2:
20481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->monitor_state = MS_REPEAT_CLAIM_TOKEN_STATE;
20491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
20501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 3:
20521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->monitor_state = MS_TRANSMIT_CLAIM_TOKEN_STATE;                                                break;
20531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 4:
20551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->monitor_state = MS_STANDBY_MONITOR_STATE;
20561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
20571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 5:
20591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->monitor_state = MS_TRANSMIT_BEACON_STATE;
20601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
20611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 6:
20631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->monitor_state = MS_ACTIVE_MONITOR_STATE;
20641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
20651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 7:
20671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->monitor_state = MS_TRANSMIT_RING_PURGE_STATE;
20681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
20691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 8:   /* diagnostic state */
20711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
20721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 9:
20741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->monitor_state = MS_BEACON_TEST_STATE;
20751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                if(smctr_lobe_media_test(dev))
20761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                {
20771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        tp->ring_status_flags = RING_STATUS_CHANGED;
20781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        tp->ring_status = AUTO_REMOVAL_ERROR;
20791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        smctr_ring_status_chg(dev);
20801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        smctr_bypass_state(dev);
20811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                }
20821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                else
20831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        smctr_issue_insert_cmd(dev);
20841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
20851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        /* case 0x0a-0xff, illegal states */
20871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        default:
20881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
20891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
20901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                tp->ring_status_flags = MONITOR_STATE_CHANGED;
20921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err = smctr_ring_status_chg(dev);
20931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                smctr_enable_16bit(dev);
20951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
20961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
20971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Type 0x02 - MAC Error Counters Interrupt
20981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         * One or more MAC Error Counter is half full
20991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *      MAC Error Counters
21001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *      Lost_FR_Error_Counter
21011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *      RCV_Congestion_Counter
21021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *      FR_copied_Error_Counter
21031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *      FREQ_Error_Counter
21041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *      Token_Error_Counter
21051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *      Line_Error_Counter
21061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *      Internal_Error_Count
21071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         */
21081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ISB_IMC_MAC_ERROR_COUNTERS:
21091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                /* Read 802.5 Error Counters */
21101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err = smctr_issue_read_ring_status_cmd(dev);
21111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
21121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Type 0x04 - MAC Type 2 Interrupt
21141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         * HOST needs to enqueue MAC Frame for transmission
21151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         * SubType Bit 15 - RQ_INIT_PDU( Request Initialization)                         * Changed from RQ_INIT_PDU to
21161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         * TRC_Status_Changed_Indicate
21171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         */
21181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ISB_IMC_MAC_TYPE_2:
21191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err = smctr_issue_read_ring_status_cmd(dev);
21201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
21211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Type 0x05 - TX Frame Interrupt (FI). */
21241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ISB_IMC_TX_FRAME:
21251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                /* BUG QUEUE for TRC stuck receive BUG */
21261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(isb_subtype & TX_PENDING_PRIORITY_2)
21271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
21281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((err = smctr_tx_complete(dev, BUG_QUEUE)) != SUCCESS)
21291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
21301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
21311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                /* NON-MAC frames only */
21331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(isb_subtype & TX_PENDING_PRIORITY_1)
21341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
21351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((err = smctr_tx_complete(dev, NON_MAC_QUEUE)) != SUCCESS)
21361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
21371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
21381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                /* MAC frames only */
21401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(isb_subtype & TX_PENDING_PRIORITY_0)
21411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        err = smctr_tx_complete(dev, MAC_QUEUE);                                break;
21421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Type 0x06 - TX END OF QUEUE (FE) */
21441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ISB_IMC_END_OF_TX_QUEUE:
21451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                /* BUG queue */
21461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(isb_subtype & TX_PENDING_PRIORITY_2)
21471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
21481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        /* ok to clear Receive FIFO overrun
21491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                         * imask send_BUG now completes.
21501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                         */
21511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        interrupt_unmask_bits |= 0x800;
21521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        tp->tx_queue_status[BUG_QUEUE] = NOT_TRANSMITING;
21541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((err = smctr_tx_complete(dev, BUG_QUEUE)) != SUCCESS)
21551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
21561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((err = smctr_restart_tx_chain(dev, BUG_QUEUE)) != SUCCESS)
21571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
21581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
21591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                /* NON-MAC queue only */
21611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(isb_subtype & TX_PENDING_PRIORITY_1)
21621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
21631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        tp->tx_queue_status[NON_MAC_QUEUE] = NOT_TRANSMITING;
21641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((err = smctr_tx_complete(dev, NON_MAC_QUEUE)) != SUCCESS)
21651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
21661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((err = smctr_restart_tx_chain(dev, NON_MAC_QUEUE)) != SUCCESS)
21671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
21681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
21691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                /* MAC queue only */
21711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(isb_subtype & TX_PENDING_PRIORITY_0)
21721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
21731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
21741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((err = smctr_tx_complete(dev, MAC_QUEUE)) != SUCCESS)
21751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
21761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        err = smctr_restart_tx_chain(dev, MAC_QUEUE);
21781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
21791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
21801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Type 0x07 - NON-MAC RX Resource Interrupt
21821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *   Subtype bit 12 - (BW) BDB warning
21831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *   Subtype bit 13 - (FW) FCB warning
21841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *   Subtype bit 14 - (BE) BDB End of chain
21851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *   Subtype bit 15 - (FE) FCB End of chain
21861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         */
21871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ISB_IMC_NON_MAC_RX_RESOURCE:
21881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                tp->rx_fifo_overrun_count = 0;
21891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                tp->receive_queue_number = NON_MAC_QUEUE;
21901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err1 = smctr_rx_frame(dev);
21911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(isb_subtype & NON_MAC_RX_RESOURCE_FE)
21931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
21941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((err = smctr_issue_resume_rx_fcb_cmd(                                                dev, NON_MAC_QUEUE)) != SUCCESS)                                                break;
21951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(tp->ptr_rx_fcb_overruns)
21971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                (*tp->ptr_rx_fcb_overruns)++;
21981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
21991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(isb_subtype & NON_MAC_RX_RESOURCE_BE)
22011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
22021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((err = smctr_issue_resume_rx_bdb_cmd(                                                dev, NON_MAC_QUEUE)) != SUCCESS)                                                break;
22031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(tp->ptr_rx_bdb_overruns)
22051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                (*tp->ptr_rx_bdb_overruns)++;
22061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
22071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err = err1;
22081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
22091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Type 0x08 - MAC RX Resource Interrupt
22111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *   Subtype bit 12 - (BW) BDB warning
22121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *   Subtype bit 13 - (FW) FCB warning
22131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *   Subtype bit 14 - (BE) BDB End of chain
22141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *   Subtype bit 15 - (FE) FCB End of chain
22151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         */
22161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ISB_IMC_MAC_RX_RESOURCE:
22171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                tp->receive_queue_number = MAC_QUEUE;
22181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err1 = smctr_rx_frame(dev);
22191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(isb_subtype & MAC_RX_RESOURCE_FE)
22211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
22221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((err = smctr_issue_resume_rx_fcb_cmd(                                                dev, MAC_QUEUE)) != SUCCESS)
22231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
22241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(tp->ptr_rx_fcb_overruns)
22261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                (*tp->ptr_rx_fcb_overruns)++;
22271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
22281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(isb_subtype & MAC_RX_RESOURCE_BE)
22301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
22311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((err = smctr_issue_resume_rx_bdb_cmd(                                                dev, MAC_QUEUE)) != SUCCESS)
22321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
22331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(tp->ptr_rx_bdb_overruns)
22351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                (*tp->ptr_rx_bdb_overruns)++;
22361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
22371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err = err1;
22381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
22391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Type 0x09 - NON_MAC RX Frame Interrupt */
22411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ISB_IMC_NON_MAC_RX_FRAME:
22421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                tp->rx_fifo_overrun_count = 0;
22431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                tp->receive_queue_number = NON_MAC_QUEUE;
22441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err = smctr_rx_frame(dev);
22451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
22461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Type 0x0A - MAC RX Frame Interrupt */
22481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ISB_IMC_MAC_RX_FRAME:
22491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                tp->receive_queue_number = MAC_QUEUE;
22501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err = smctr_rx_frame(dev);
22511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
22521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Type 0x0B - TRC status
22541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         * TRC has encountered an error condition
22551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         * subtype bit 14 - transmit FIFO underrun
22561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         * subtype bit 15 - receive FIFO overrun
22571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         */
22581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ISB_IMC_TRC_FIFO_STATUS:
22591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(isb_subtype & TRC_FIFO_STATUS_TX_UNDERRUN)
22601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
22611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(tp->ptr_tx_fifo_underruns)
22621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                (*tp->ptr_tx_fifo_underruns)++;
22631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
22641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(isb_subtype & TRC_FIFO_STATUS_RX_OVERRUN)
22661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
22671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        /* update overrun stuck receive counter
22681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                         * if >= 3, has to clear it by sending
22691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                         * back to back frames. We pick
22701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                         * DAT(duplicate address MAC frame)
22711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                         */
22721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        tp->rx_fifo_overrun_count++;
22731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(tp->rx_fifo_overrun_count >= 3)
22751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        {
22761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->rx_fifo_overrun_count = 0;
22771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                /* delay clearing fifo overrun
22791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                 * imask till send_BUG tx
22801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                 * complete posted
22811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                 */
22821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                interrupt_unmask_bits &= (~0x800);
22831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                printk(KERN_CRIT "Jay please send bug\n");//                                              smctr_send_bug(dev);
22841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        }
22851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(tp->ptr_rx_fifo_overruns)
22871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                (*tp->ptr_rx_fifo_overruns)++;
22881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
22891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err = SUCCESS;
22911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
22921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
22931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Type 0x0C - Action Command Status Interrupt
22941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         * Subtype bit 14 - CB end of command chain (CE)
22951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         * Subtype bit 15 - CB command interrupt (CI)
22961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         */
22971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ISB_IMC_COMMAND_STATUS:
22981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err = SUCCESS;
22991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(tp->acb_head->cmd == ACB_CMD_HIC_NOP)
23001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
23011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        printk(KERN_ERR "i1\n");
23021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        smctr_disable_16bit(dev);
23031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        /* XXXXXXXXXXXXXXXXX */
23051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                /*      err = UM_Interrupt(dev); */
23061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        smctr_enable_16bit(dev);
23081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
23091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                else
23101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
23111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((tp->acb_head->cmd
23128e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches					    == ACB_CMD_READ_TRC_STATUS) &&
23138e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches					   (tp->acb_head->subcmd
23148e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches					    == RW_TRC_STATUS_BLOCK))
23151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        {
231679ea13ce07c951bb4d95471e7300baa0f1be9e78Al Viro                                                if(tp->ptr_bcn_type)
23171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                {
23181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        *(tp->ptr_bcn_type)
23191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                                = (__u32)((SBlock *)tp->misc_command_data)->BCN_Type;
23201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                }
23211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & ERROR_COUNTERS_CHANGED)
23231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                {
23241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        smctr_update_err_stats(dev);
23251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                }
23261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & TI_NDIS_RING_STATUS_CHANGED)
23281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                {
23291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        tp->ring_status
23301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                                = ((SBlock*)tp->misc_command_data)->TI_NDIS_Ring_Status;
23311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        smctr_disable_16bit(dev);
23321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        err = smctr_ring_status_chg(dev);
23331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        smctr_enable_16bit(dev);
23348e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches                                                        if((tp->ring_status & REMOVE_RECEIVED) &&
23358e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches							   (tp->config_word0 & NO_AUTOREMOVE))
23361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        {
23371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                                smctr_issue_remove_cmd(dev);
23381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        }
23391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        if(err != SUCCESS)
23411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        {
23421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                                tp->acb_pending = 0;
23431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                                break;
23441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        }
23451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                }
23461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & UNA_CHANGED)
23481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                {
23491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        if(tp->ptr_una)
23501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        {
23511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                                tp->ptr_una[0] = SWAP_BYTES(((SBlock *)tp->misc_command_data)->UNA[0]);
23521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                                tp->ptr_una[1] = SWAP_BYTES(((SBlock *)tp->misc_command_data)->UNA[1]);
23531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                                tp->ptr_una[2] = SWAP_BYTES(((SBlock *)tp->misc_command_data)->UNA[2]);
23541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        }
23551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                }
23571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                if(((SBlock *)tp->misc_command_data)->Status_CHG_Indicate & READY_TO_SEND_RQ_INIT)                                                {
23591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        err = smctr_send_rq_init(dev);
23601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                }
23611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        }
23621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
23631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                tp->acb_pending = 0;
23651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
23661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Type 0x0D - MAC Type 1 interrupt
23681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         * Subtype -- 00 FR_BCN received at S12
23691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *            01 FR_BCN received at S21
23701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *            02 FR_DAT(DA=MA, A<>0) received at S21
23711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *            03 TSM_EXP at S21
23721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *            04 FR_REMOVE received at S42
23731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *            05 TBR_EXP, BR_FLAG_SET at S42
23741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         *            06 TBT_EXP at S53
23751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         */
23761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ISB_IMC_MAC_TYPE_1:
23771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(isb_subtype > 8)
23781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
23791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        err = HARDWARE_FAILED;
23801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        break;
23811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
23821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err = SUCCESS;
23841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                switch(isb_subtype)
23851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
23861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 0:
23871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->join_state = JS_BYPASS_STATE;
23881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                if(tp->status != CLOSED)
23891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                {
23901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        tp->status = CLOSED;
23911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        err = smctr_status_chg(dev);
23921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                }
23931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
23941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 1:
23961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->join_state = JS_LOBE_TEST_STATE;
23971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
23981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 2:
24001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->join_state = JS_DETECT_MONITOR_PRESENT_STATE;
24011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
24021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 3:
24041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->join_state = JS_AWAIT_NEW_MONITOR_STATE;
24051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
24061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 4:
24081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->join_state = JS_DUPLICATE_ADDRESS_TEST_STATE;
24091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
24101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 5:
24121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->join_state = JS_NEIGHBOR_NOTIFICATION_STATE;
24131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
24141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 6:
24161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->join_state = JS_REQUEST_INITIALIZATION_STATE;
24171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
24181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 7:
24201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->join_state = JS_JOIN_COMPLETE_STATE;
24211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->status = OPEN;
24221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                err = smctr_status_chg(dev);
24231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
24241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        case 8:
24261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->join_state = JS_BYPASS_WAIT_STATE;
24271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                break;
24281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
24291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break ;
24301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Type 0x0E - TRC Initialization Sequence Interrupt
24321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         * Subtype -- 00-FF Initializatin sequence complete
24331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         */
24341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ISB_IMC_TRC_INTRNL_TST_STATUS:
24351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                tp->status = INITIALIZED;
24361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                smctr_disable_16bit(dev);
24371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err = smctr_status_chg(dev);
24381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                smctr_enable_16bit(dev);
24391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
24401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* other interrupt types, illegal */
24421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        default:
24431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
24441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
24451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(err != SUCCESS)
24471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
24481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
24491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Checking the ack code instead of the unmask bits here is because :
24511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * while fixing the stuck receive, DAT frame are sent and mask off
24521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * FIFO overrun interrupt temporarily (interrupt_unmask_bits = 0)
24531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * but we still want to issue ack to ISB
24541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
24551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(!(interrupt_ack_code & 0xff00))
24561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_issue_int_ack(dev, interrupt_ack_code, interrupt_unmask_bits);
24571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_disable_16bit(dev);
24591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_enable_bic_int(dev);
24601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        spin_unlock(&tp->lock);
24611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        return IRQ_HANDLED;
24631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_enable_int_cmd(struct net_device *dev,
24661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 interrupt_enable_mask)
24671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
24691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
24701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_while_cbusy(dev)))
2472807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
24731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->int_mask_control  = interrupt_enable_mask;
24751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->valid_command     = SCLB_VALID | SCLB_CMD_CLEAR_INTERRUPT_MASK;
24761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_ctrl_attention(dev);
24781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2479807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
24801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_int_ack(struct net_device *dev, __u16 iack_code, __u16 ibits)
24831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
24841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
24851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_wait_while_cbusy(dev))
2487807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -1;
24881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->int_mask_control = ibits;
24901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->iack_code = iack_code << 1; /* use the offset from base */        tp->sclb_ptr->resume_control = 0;
24911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_IACK_CODE_VALID | SCLB_CMD_CLEAR_INTERRUPT_MASK;
24921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_ctrl_attention(dev);
24941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2495807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
24961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
24971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
24981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_init_timers_cmd(struct net_device *dev)
24991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
25001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
25011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i;
25021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
25031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 *pTimer_Struc = (__u16 *)tp->misc_command_data;
25041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_while_cbusy(dev)))
2506807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
25071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_cmd(dev)))
2509807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
25101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->config_word0 = THDREN | DMA_TRIGGER | USETPT | NO_AUTOREMOVE;
25121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->config_word1 = 0;
25131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25148e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches        if((tp->media_type == MEDIA_STP_16) ||
25158e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	   (tp->media_type == MEDIA_UTP_16) ||
25168e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	   (tp->media_type == MEDIA_STP_16_UTP_16))
25171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
25181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 |= FREQ_16MB_BIT;
25191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
25201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->mode_bits & EARLY_TOKEN_REL)
25221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 |= ETREN;
25231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->mode_bits & LOOPING_MODE_MASK)
25251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 |= RX_OWN_BIT;
25261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
25271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 &= ~RX_OWN_BIT;
25281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->receive_mask & PROMISCUOUS_MODE)
25301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 |= PROMISCUOUS_BIT;
25311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
25321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 &= ~PROMISCUOUS_BIT;
25331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->receive_mask & ACCEPT_ERR_PACKETS)
25351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 |= SAVBAD_BIT;
25361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
25371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 &= ~SAVBAD_BIT;
25381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->receive_mask & ACCEPT_ATT_MAC_FRAMES)
25401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 |= RXATMAC;
25411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
25421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word0 &= ~RXATMAC;
25431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->receive_mask & ACCEPT_MULTI_PROM)
25451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word1 |= MULTICAST_ADDRESS_BIT;
25461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
25471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word1 &= ~MULTICAST_ADDRESS_BIT;
25481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->receive_mask & ACCEPT_SOURCE_ROUTING_SPANNING)
25501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word1 |= SOURCE_ROUTING_SPANNING_BITS;
25511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
25521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
25531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(tp->receive_mask & ACCEPT_SOURCE_ROUTING)
25541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->config_word1 |= SOURCE_ROUTING_EXPLORER_BIT;
25551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
25561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->config_word1 &= ~SOURCE_ROUTING_SPANNING_BITS;
25571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
25581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25598e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches        if((tp->media_type == MEDIA_STP_16) ||
25608e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	   (tp->media_type == MEDIA_UTP_16) ||
25618e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	   (tp->media_type == MEDIA_STP_16_UTP_16))
25621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
25631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word1 |= INTERFRAME_SPACING_16;
25641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
25651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
25661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->config_word1 |= INTERFRAME_SPACING_4;
25671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = tp->config_word0;
25691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = tp->config_word1;
25701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
25718e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches        if((tp->media_type == MEDIA_STP_4) ||
25728e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	   (tp->media_type == MEDIA_UTP_4) ||
25738e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	   (tp->media_type == MEDIA_STP_4_UTP_4))
25741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
25751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x00FA;       /* prescale */
25761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x2710;       /* TPT_limit */
25771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x2710;       /* TQP_limit */
25781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x0A28;       /* TNT_limit */
25791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x3E80;       /* TBT_limit */
25801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x3A98;       /* TSM_limit */
25811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x1B58;       /* TAM_limit */
25821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x00C8;       /* TBR_limit */
25831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x07D0;       /* TER_limit */
25841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x000A;       /* TGT_limit */
25851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x1162;       /* THT_limit */
25861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x07D0;       /* TRR_limit */
25871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x1388;       /* TVX_limit */
25881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x0000;       /* reserved */
25891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
25901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
25911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
25921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x03E8;       /* prescale */
25931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x9C40;       /* TPT_limit */
25941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x9C40;       /* TQP_limit */
25951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x0A28;       /* TNT_limit */
25961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x3E80;       /* TBT_limit */
25971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x3A98;       /* TSM_limit */
25981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x1B58;       /* TAM_limit */
25991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x00C8;       /* TBR_limit */
26001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x07D0;       /* TER_limit */
26011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x000A;       /* TGT_limit */
26021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x4588;       /* THT_limit */
26031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x1F40;       /* TRR_limit */
26041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x4E20;       /* TVX_limit */
26051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = 0x0000;       /* reserved */
26061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
26071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Set node address. */
26091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = dev->dev_addr[0] << 8
26101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                | (dev->dev_addr[1] & 0xFF);
26111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = dev->dev_addr[2] << 8
26121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                | (dev->dev_addr[3] & 0xFF);
26131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = dev->dev_addr[4] << 8
26141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                | (dev->dev_addr[5] & 0xFF);
26151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Set group address. */
26171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = tp->group_address_0 << 8
26181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                | tp->group_address_0 >> 8;
26191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = tp->group_address[0] << 8
26201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                | tp->group_address[0] >> 8;
26211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = tp->group_address[1] << 8
26221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                | tp->group_address[1] >> 8;
26231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Set functional address. */
26251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = tp->functional_address_0 << 8
26261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                | tp->functional_address_0 >> 8;
26271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = tp->functional_address[0] << 8
26281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                | tp->functional_address[0] >> 8;
26291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = tp->functional_address[1] << 8
26301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                | tp->functional_address[1] >> 8;
26311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Set Bit-Wise group address. */
26331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = tp->bitwise_group_address[0] << 8
26341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                | tp->bitwise_group_address[0] >> 8;
26351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = tp->bitwise_group_address[1] << 8
26361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                | tp->bitwise_group_address[1] >> 8;
26371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Set ring number address. */
26391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = tp->source_ring_number;
26401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = tp->target_ring_number;
26411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Physical drop number. */
26431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = (unsigned short)0;
26441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *pTimer_Struc++ = (unsigned short)0;
26451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Product instance ID. */
26471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < 9; i++)
26481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *pTimer_Struc++ = (unsigned short)0;
26491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_INIT_TRC_TIMERS, 0);
26511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2652807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
26531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
26541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_init_txrx_cmd(struct net_device *dev)
26561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
26571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
26581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i;
26591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
26601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        void **txrx_ptrs = (void *)tp->misc_command_data;
26611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_while_cbusy(dev)))
2663807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
26641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_cmd(dev)))
26661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
26671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_ERR "%s: Hardware failure\n", dev->name);
2668807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
26691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
26701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize Transmit Queue Pointers that are used, to point to
26721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * a single FCB.
26731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
26741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < NUM_TX_QS_USED; i++)
26751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *txrx_ptrs++ = (void *)TRC_POINTER(tp->tx_fcb_head[i]);
26761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize Transmit Queue Pointers that are NOT used to ZERO. */
26781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(; i < MAX_TX_QS; i++)
26791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *txrx_ptrs++ = (void *)0;
26801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize Receive Queue Pointers (MAC and Non-MAC) that are
26821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * used, to point to a single FCB and a BDB chain of buffers.
26831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
26841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < NUM_RX_QS_USED; i++)
26851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
26861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *txrx_ptrs++ = (void *)TRC_POINTER(tp->rx_fcb_head[i]);
26871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *txrx_ptrs++ = (void *)TRC_POINTER(tp->rx_bdb_head[i]);
26881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
26891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize Receive Queue Pointers that are NOT used to ZERO. */
26911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(; i < MAX_RX_QS; i++)
26921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
26931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *txrx_ptrs++ = (void *)0;
26941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *txrx_ptrs++ = (void *)0;
26951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
26961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
26971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_INIT_TX_RX, 0);
26981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2699807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
27001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_insert_cmd(struct net_device *dev)
27031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
27051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd(dev, ACB_CMD_INSERT, ACB_SUB_CMD_NOP);
27071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2708807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
27091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_read_ring_status_cmd(struct net_device *dev)
27121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
27141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_while_cbusy(dev)))
2716807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
27171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_cmd(dev)))
2719807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
27201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_READ_TRC_STATUS,
27221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                RW_TRC_STATUS_BLOCK);
27231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2724807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
27251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_read_word_cmd(struct net_device *dev, __u16 aword_cnt)
27281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
27301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_while_cbusy(dev)))
2732807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
27331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_cmd(dev)))
2735807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
27361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_READ_VALUE,
27381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                aword_cnt);
27391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2740807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
27411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_remove_cmd(struct net_device *dev)
27441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
27461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
27471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_while_cbusy(dev)))
2749807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
27501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->resume_control    = 0;
27521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->valid_command     = SCLB_VALID | SCLB_CMD_REMOVE;
27531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_ctrl_attention(dev);
27551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2756807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
27571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_resume_acb_cmd(struct net_device *dev)
27601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
27621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
27631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_while_cbusy(dev)))
2765807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
27661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->resume_control = SCLB_RC_ACB;
27681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->valid_command  = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
27691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->acb_pending = 1;
27711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_ctrl_attention(dev);
27731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2774807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
27751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_resume_rx_bdb_cmd(struct net_device *dev, __u16 queue)
27781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
27801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
27811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_while_cbusy(dev)))
2783807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
27841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(queue == MAC_QUEUE)
27861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->sclb_ptr->resume_control = SCLB_RC_RX_MAC_BDB;
27871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
27881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->sclb_ptr->resume_control = SCLB_RC_RX_NON_MAC_BDB;
27891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
27911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_ctrl_attention(dev);
27931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2794807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
27951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
27961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
27971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_resume_rx_fcb_cmd(struct net_device *dev, __u16 queue)
27981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
27991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
28001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
28021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_issue_resume_rx_fcb_cmd\n", dev->name);
28031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_wait_while_cbusy(dev))
2805807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -1;
28061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(queue == MAC_QUEUE)
28081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->sclb_ptr->resume_control = SCLB_RC_RX_MAC_FCB;
28091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
28101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->sclb_ptr->resume_control = SCLB_RC_RX_NON_MAC_FCB;
28111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->valid_command = SCLB_VALID | SCLB_RESUME_CONTROL_VALID;
28131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_ctrl_attention(dev);
28151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2816807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
28171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
28181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_resume_tx_fcb_cmd(struct net_device *dev, __u16 queue)
28201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
28221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
28241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_issue_resume_tx_fcb_cmd\n", dev->name);
28251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_wait_while_cbusy(dev))
2827807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -1;
28281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->resume_control = (SCLB_RC_TFCB0 << queue);
28301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sclb_ptr->valid_command = SCLB_RESUME_CONTROL_VALID | SCLB_VALID;
28311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_ctrl_attention(dev);
28331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2834807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
28351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
28361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_test_internal_rom_cmd(struct net_device *dev)
28381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
28401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
28421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                TRC_INTERNAL_ROM_TEST);
28431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2844807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
28451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
28461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_test_hic_cmd(struct net_device *dev)
28481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
28501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd(dev, ACB_CMD_HIC_TEST,
28521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                TRC_HOST_INTERFACE_REG_TEST);
28531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2854807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
28551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
28561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_test_mac_reg_cmd(struct net_device *dev)
28581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
28601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
28621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                TRC_MAC_REGISTERS_TEST);
28631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2864807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
28651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
28661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_trc_loopback_cmd(struct net_device *dev)
28681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
28701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
28721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                TRC_INTERNAL_LOOPBACK);
28731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2874807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
28751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
28761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_tri_loopback_cmd(struct net_device *dev)
28781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
28801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
28821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                TRC_TRI_LOOPBACK);
28831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2884807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
28851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
28861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_write_byte_cmd(struct net_device *dev,
28881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        short aword_cnt, void *byte)
28891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
28901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_local *tp = netdev_priv(dev);
28911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int iword, ibyte;
28921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
28931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_while_cbusy(dev)))
2895807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
28961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_cmd(dev)))
2898807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
28991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(iword = 0, ibyte = 0; iword < (unsigned int)(aword_cnt & 0xff);
29011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	iword++, ibyte += 2)
29021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
29031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->misc_command_data[iword] = (*((__u8 *)byte + ibyte) << 8)
29041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			| (*((__u8 *)byte + ibyte + 1));
29051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
29061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2907807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE,
2908807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet		aword_cnt);
29091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_issue_write_word_cmd(struct net_device *dev,
29121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        short aword_cnt, void *word)
29131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
29151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i, err;
29161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_while_cbusy(dev)))
2918807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
29191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_cmd(dev)))
2921807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
29221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < (unsigned int)(aword_cnt & 0xff); i++)
29241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->misc_command_data[i] = *((__u16 *)word + i);
29251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd_w_data(dev, ACB_CMD_MCT_WRITE_VALUE,
29271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                aword_cnt);
29281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2929807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
29301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_join_complete_state(struct net_device *dev)
29331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
29351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
29371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                JS_JOIN_COMPLETE_STATE);
29381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2939807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
29401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_link_tx_fcbs_to_bdbs(struct net_device *dev)
29431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
29451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i, j;
29461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
29471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        BDBlock *bdb;
29481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < NUM_TX_QS_USED; i++)
29501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
29511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb = tp->tx_fcb_head[i];
29521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb = tp->tx_bdb_head[i];
29531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for(j = 0; j < tp->num_tx_fcbs[i]; j++)
29551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
29561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->bdb_ptr            = bdb;
29571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb->trc_bdb_ptr        = TRC_POINTER(bdb);
29581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        fcb = (FCBlock *)((char *)fcb + sizeof(FCBlock));
29591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        bdb = (BDBlock *)((char *)bdb + sizeof(BDBlock));
29601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
29611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
29621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2963807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
29641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
29651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_load_firmware(struct net_device *dev)
29671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
29681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
29690f805b86c9492c294c710de8539a8be68b521a86David Woodhouse	const struct firmware *fw;
29701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 i, checksum = 0;
29711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err = 0;
29721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
29741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_load_firmware\n", dev->name);
29751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29760f805b86c9492c294c710de8539a8be68b521a86David Woodhouse	if (request_firmware(&fw, "tr_smctr.bin", &dev->dev)) {
29770f805b86c9492c294c710de8539a8be68b521a86David Woodhouse		printk(KERN_ERR "%s: firmware not found\n", dev->name);
2978807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet		return UCODE_NOT_PRESENT;
29790f805b86c9492c294c710de8539a8be68b521a86David Woodhouse	}
29800f805b86c9492c294c710de8539a8be68b521a86David Woodhouse
29811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->num_of_tx_buffs     = 4;
29821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->mode_bits          |= UMAC;
29831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->receive_mask        = 0;
29841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->max_packet_size     = 4177;
29851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Can only upload the firmware once per adapter reset. */
29870f805b86c9492c294c710de8539a8be68b521a86David Woodhouse        if (tp->microcode_version != 0) {
29880f805b86c9492c294c710de8539a8be68b521a86David Woodhouse		err = (UCODE_PRESENT);
29890f805b86c9492c294c710de8539a8be68b521a86David Woodhouse		goto out;
29900f805b86c9492c294c710de8539a8be68b521a86David Woodhouse	}
29911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
29921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Verify the firmware exists and is there in the right amount. */
29938e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches        if (!fw->data ||
29948e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	    (*(fw->data + UCODE_VERSION_OFFSET) < UCODE_VERSION))
29951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
29960f805b86c9492c294c710de8539a8be68b521a86David Woodhouse                err = (UCODE_NOT_PRESENT);
29970f805b86c9492c294c710de8539a8be68b521a86David Woodhouse		goto out;
29981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
29991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* UCODE_SIZE is not included in Checksum. */
30010f805b86c9492c294c710de8539a8be68b521a86David Woodhouse        for(i = 0; i < *((__u16 *)(fw->data + UCODE_SIZE_OFFSET)); i += 2)
30020f805b86c9492c294c710de8539a8be68b521a86David Woodhouse                checksum += *((__u16 *)(fw->data + 2 + i));
30030f805b86c9492c294c710de8539a8be68b521a86David Woodhouse        if (checksum) {
30040f805b86c9492c294c710de8539a8be68b521a86David Woodhouse		err = (UCODE_NOT_PRESENT);
30050f805b86c9492c294c710de8539a8be68b521a86David Woodhouse		goto out;
30060f805b86c9492c294c710de8539a8be68b521a86David Woodhouse	}
30071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* At this point we have a valid firmware image, lets kick it on up. */
30091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_enable_adapter_ram(dev);
30101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_enable_16bit(dev);
30111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_page(dev, (__u8 *)tp->ram_access);
30121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30138e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches        if((smctr_checksum_firmware(dev)) ||
30148e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	   (*(fw->data + UCODE_VERSION_OFFSET) > tp->microcode_version))
30151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
30161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_enable_adapter_ctrl_store(dev);
30171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Zero out ram space for firmware. */
30191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for(i = 0; i < CS_RAM_SIZE; i += 2)
30201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        *((__u16 *)(tp->ram_access + i)) = 0;
30211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30220f805b86c9492c294c710de8539a8be68b521a86David Woodhouse                smctr_decode_firmware(dev, fw);
30231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30240f805b86c9492c294c710de8539a8be68b521a86David Woodhouse                tp->microcode_version = *(fw->data + UCODE_VERSION_OFFSET);                *((__u16 *)(tp->ram_access + CS_RAM_VERSION_OFFSET))
30251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        = (tp->microcode_version << 8);
30261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *((__u16 *)(tp->ram_access + CS_RAM_CHECKSUM_OFFSET))
30271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        = ~(tp->microcode_version << 8) + 1;
30281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_disable_adapter_ctrl_store(dev);
30301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(smctr_checksum_firmware(dev))
30321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        err = HARDWARE_FAILED;
30331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
30341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
30351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                err = UCODE_PRESENT;
30361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_disable_16bit(dev);
30380f805b86c9492c294c710de8539a8be68b521a86David Woodhouse out:
30390f805b86c9492c294c710de8539a8be68b521a86David Woodhouse	release_firmware(fw);
3040807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
30411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
30421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_load_node_addr(struct net_device *dev)
30441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
30451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ioaddr = dev->base_addr;
30461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i;
30471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 r;
30481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < 6; i++)
30501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
30511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                r = inb(ioaddr + LAR0 + i);
30521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                dev->dev_addr[i] = (char)r;
30531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
30541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        dev->addr_len = 6;
30551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3056807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
30571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
30581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Lobe Media Test.
30601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * During the transmission of the initial 1500 lobe media MAC frames,
30611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the phase lock loop in the 805 chip may lock, and then un-lock, causing
30621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the 825 to go into a PURGE state. When performing a PURGE, the MCT
30631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * microcode will not transmit any frames given to it by the host, and
30641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will consequently cause a timeout.
30651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
30661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE 1: If the monitor_state is MS_BEACON_TEST_STATE, all transmit
3067025dfdafe77f20b3890981a394774baab7b9c827Frederik Schwarzer * queues other than the one used for the lobe_media_test should be
30681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * disabled.!?
30691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
30701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * NOTE 2: If the monitor_state is MS_BEACON_TEST_STATE and the receive_mask
307125985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * has any multi-cast or promiscuous bits set, the receive_mask needs to
307225985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * be changed to clear the multi-cast or promiscuous mode bits, the lobe_test
30731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * run, and then the receive mask set back to its original value if the test
30741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is successful.
30751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
30761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_lobe_media_test(struct net_device *dev)
30771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
30781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
30791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i, perror = 0;
30801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned short saved_rcv_mask;
30811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
30831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_lobe_media_test\n", dev->name);
30841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Clear receive mask for lobe test. */
30861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        saved_rcv_mask          = tp->receive_mask;
30871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->receive_mask        = 0;
30881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_chg_rx_mask(dev);
30901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Setup the lobe media test. */
30921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_lobe_media_test_cmd(dev);
30931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_wait_cmd(dev))
3094582b95c2709cd58913ec2a31b0266ba0aa67b03dJulia Lawall		goto err;
30951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
30961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Tx lobe media test frames. */
30971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < 1500; ++i)
30981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
30991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(smctr_send_lobe_media_test(dev))
31001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
31011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(perror)
3102582b95c2709cd58913ec2a31b0266ba0aa67b03dJulia Lawall				goto err;
31031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        else
31041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        {
31051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                perror = 1;
31061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(smctr_lobe_media_test_cmd(dev))
3107582b95c2709cd58913ec2a31b0266ba0aa67b03dJulia Lawall					goto err;
31081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        }
31091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
31101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
31111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_send_dat(dev))
31131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
31141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(smctr_send_dat(dev))
3115582b95c2709cd58913ec2a31b0266ba0aa67b03dJulia Lawall			goto err;
31161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
31171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Check if any frames received during test. */
31198e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches        if((tp->rx_fcb_curr[MAC_QUEUE]->frame_status) ||
31208e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	   (tp->rx_fcb_curr[NON_MAC_QUEUE]->frame_status))
31218e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches		goto err;
31221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Set receive mask to "Promisc" mode. */
31241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->receive_mask = saved_rcv_mask;
31251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_chg_rx_mask(dev);
31271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3128582b95c2709cd58913ec2a31b0266ba0aa67b03dJulia Lawall	 return 0;
3129582b95c2709cd58913ec2a31b0266ba0aa67b03dJulia Lawallerr:
3130582b95c2709cd58913ec2a31b0266ba0aa67b03dJulia Lawall	smctr_reset_adapter(dev);
3131582b95c2709cd58913ec2a31b0266ba0aa67b03dJulia Lawall	tp->status = CLOSED;
3132582b95c2709cd58913ec2a31b0266ba0aa67b03dJulia Lawall	return LOBE_MEDIA_TEST_FAILED;
31331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_lobe_media_test_cmd(struct net_device *dev)
31361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
31381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
31391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
31411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_lobe_media_test_cmd\n", dev->name);
31421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Change to lobe media test state. */
31441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->monitor_state != MS_BEACON_TEST_STATE)
31451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
31461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_lobe_media_test_state(dev);
31471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(smctr_wait_cmd(dev))
31481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
31491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_ERR "Lobe Failed test state\n");
3150807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                        return LOBE_MEDIA_TEST_FAILED;
31511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
31521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
31531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd(dev, ACB_CMD_MCT_TEST,
31551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                TRC_LOBE_MEDIA_TEST);
31561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3157807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
31581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_lobe_media_test_state(struct net_device *dev)
31611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
31631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_setup_single_cmd(dev, ACB_CMD_CHANGE_JOIN_STATE,
31651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                JS_LOBE_TEST_STATE);
31661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3167807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
31681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
31691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_8025_hdr(struct net_device *dev,
31711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_HEADER *rmf, MAC_HEADER *tmf, __u16 ac_fc)
31721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
31731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->ac = MSB(ac_fc);                 /* msb is access control */
31741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->fc = LSB(ac_fc);                 /* lsb is frame control */
31751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->sa[0] = dev->dev_addr[0];
31771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->sa[1] = dev->dev_addr[1];
31781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->sa[2] = dev->dev_addr[2];
31791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->sa[3] = dev->dev_addr[3];
31801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->sa[4] = dev->dev_addr[4];
31811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->sa[5] = dev->dev_addr[5];
31821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        switch(tmf->vc)
31841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
31851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Send RQ_INIT to RPS */
31861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case RQ_INIT:
31871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[0] = 0xc0;
31881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[1] = 0x00;
31891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[2] = 0x00;
31901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[3] = 0x00;
31911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[4] = 0x00;
31921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[5] = 0x02;
31931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
31941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
31951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Send RPT_TX_FORWARD to CRS */
31961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case RPT_TX_FORWARD:
31971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[0] = 0xc0;
31981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[1] = 0x00;
31991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[2] = 0x00;
32001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[3] = 0x00;
32011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[4] = 0x00;
32021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[5] = 0x10;
32031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
32041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* Everything else goes to sender */
32061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                default:
32071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[0] = rmf->sa[0];
32081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[1] = rmf->sa[1];
32091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[2] = rmf->sa[2];
32101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[3] = rmf->sa[3];
32111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[4] = rmf->sa[4];
32121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tmf->da[5] = rmf->sa[5];
32131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
32141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
32151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3216807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
32171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_access_pri(struct net_device *dev, MAC_SUB_VECTOR *tsv)
32201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
32221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = AUTHORIZED_ACCESS_PRIORITY;
32241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_AUTHORIZED_ACCESS_PRIORITY;
32251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[0] = MSB(tp->authorized_access_priority);
32271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[1] = LSB(tp->authorized_access_priority);
32281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3229807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return 0;
32301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_addr_mod(struct net_device *dev, MAC_SUB_VECTOR *tsv)
32331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = ADDRESS_MODIFER;
32351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_ADDRESS_MODIFER;
32361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[0] = 0;
32381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[1] = 0;
32391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3240807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
32411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_auth_funct_class(struct net_device *dev,
32441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv)
32451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
32471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = AUTHORIZED_FUNCTION_CLASS;
32491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_AUTHORIZED_FUNCTION_CLASS;
32501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[0] = MSB(tp->authorized_function_classes);
32521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[1] = LSB(tp->authorized_function_classes);
32531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3254807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
32551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_corr(struct net_device *dev,
32581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv, __u16 correlator)
32591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = CORRELATOR;
32611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_CORRELATOR;
32621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[0] = MSB(correlator);
32641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[1] = LSB(correlator);
32651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3266807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
32671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_funct_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
32701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
32721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_get_functional_address(dev);
32741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = FUNCTIONAL_ADDRESS;
32761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_FUNCTIONAL_ADDRESS;
32771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[0] = MSB(tp->misc_command_data[0]);
32791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[1] = LSB(tp->misc_command_data[0]);
32801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[2] = MSB(tp->misc_command_data[1]);
32821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[3] = LSB(tp->misc_command_data[1]);
32831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3284807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
32851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
32861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_group_addr(struct net_device *dev, MAC_SUB_VECTOR *tsv)
32881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
32891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
32901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_get_group_address(dev);
32921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = GROUP_ADDRESS;
32941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_GROUP_ADDRESS;
32951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[0] = MSB(tp->misc_command_data[0]);
32971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[1] = LSB(tp->misc_command_data[0]);
32981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[2] = MSB(tp->misc_command_data[1]);
33001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[3] = LSB(tp->misc_command_data[1]);
33011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Set Group Address Sub-vector to all zeros if only the
33031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * Group Address/Functional Address Indicator is set.
33041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
33058e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches        if(tsv->svv[0] == 0x80 && tsv->svv[1] == 0x00 &&
33068e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	   tsv->svv[2] == 0x00 && tsv->svv[3] == 0x00)
33071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tsv->svv[0] = 0x00;
33081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3309807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
33101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
33111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_phy_drop_num(struct net_device *dev,
33131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv)
33141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
33151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
33161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_get_physical_drop_number(dev);
33181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = PHYSICAL_DROP;
33201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_PHYSICAL_DROP;
33211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[0] = MSB(tp->misc_command_data[0]);
33231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[1] = LSB(tp->misc_command_data[0]);
33241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[2] = MSB(tp->misc_command_data[1]);
33261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[3] = LSB(tp->misc_command_data[1]);
33271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3328807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
33291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
33301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_product_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
33321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
33331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int i;
33341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = PRODUCT_INSTANCE_ID;
33361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_PRODUCT_INSTANCE_ID;
33371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < 18; i++)
33391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tsv->svv[i] = 0xF0;
33401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3341807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
33421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
33431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_station_id(struct net_device *dev, MAC_SUB_VECTOR *tsv)
33451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
33461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
33471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_get_station_id(dev);
33491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = STATION_IDENTIFER;
33511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_STATION_IDENTIFER;
33521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[0] = MSB(tp->misc_command_data[0]);
33541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[1] = LSB(tp->misc_command_data[0]);
33551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[2] = MSB(tp->misc_command_data[1]);
33571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[3] = LSB(tp->misc_command_data[1]);
33581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[4] = MSB(tp->misc_command_data[2]);
33601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[5] = LSB(tp->misc_command_data[2]);
33611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3362807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
33631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
33641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_ring_station_status(struct net_device *dev,
33661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR * tsv)
33671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
33681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = RING_STATION_STATUS;
33691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_RING_STATION_STATUS;
33701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[0] = 0;
33721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[1] = 0;
33731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[2] = 0;
33741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[3] = 0;
33751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[4] = 0;
33761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[5] = 0;
33771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3378807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
33791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
33801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_ring_station_version(struct net_device *dev,
33821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv)
33831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
33841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
33851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = RING_STATION_VERSION_NUMBER;
33871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_RING_STATION_VERSION_NUMBER;
33881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[0] = 0xe2;            /* EBCDIC - S */
33901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[1] = 0xd4;            /* EBCDIC - M */
33911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[2] = 0xc3;            /* EBCDIC - C */
33921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[3] = 0x40;            /* EBCDIC -   */
33931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[4] = 0xe5;            /* EBCDIC - V */
33941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[5] = 0xF0 + (tp->microcode_version >> 4);
33951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[6] = 0xF0 + (tp->microcode_version & 0x0f);
33961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[7] = 0x40;            /* EBCDIC -   */
33971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[8] = 0xe7;            /* EBCDIC - X */
33981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
33991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->extra_info & CHIP_REV_MASK)
34001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tsv->svv[9] = 0xc5;    /* EBCDIC - E */
34011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
34021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tsv->svv[9] = 0xc4;    /* EBCDIC - D */
34031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3404807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
34051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
34061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_tx_status_code(struct net_device *dev,
34081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv, __u16 tx_fstatus)
34091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
34101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = TRANSMIT_STATUS_CODE;
34111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_TRANSMIT_STATUS_CODE;
34121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
341326c080bf8308449330037f91daa3ac0a7c41023eJay Schulist	tsv->svv[0] = ((tx_fstatus & 0x0100 >> 6) | IBM_PASS_SOURCE_ADDR);
34141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Stripped frame status of Transmitted Frame */
34161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[1] = tx_fstatus & 0xff;
34171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3418807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
34191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
34201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_upstream_neighbor_addr(struct net_device *dev,
34221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv)
34231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
34241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
34251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_get_upstream_neighbor_addr(dev);
34271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = UPSTREAM_NEIGHBOR_ADDRESS;
34291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_UPSTREAM_NEIGHBOR_ADDRESS;
34301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[0] = MSB(tp->misc_command_data[0]);
34321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[1] = LSB(tp->misc_command_data[0]);
34331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[2] = MSB(tp->misc_command_data[1]);
34351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[3] = LSB(tp->misc_command_data[1]);
34361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[4] = MSB(tp->misc_command_data[2]);
34381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svv[5] = LSB(tp->misc_command_data[2]);
34391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3440807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
34411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
34421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_make_wrap_data(struct net_device *dev, MAC_SUB_VECTOR *tsv)
34441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
34451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svi = WRAP_DATA;
34461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv->svl = S_WRAP_DATA;
34471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3448807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
34491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
34501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
34521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Open/initialize the board. This is called sometime after
34531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * booting when the 'ifconfig' program is run.
34541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
34551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This routine should set everything up anew at each open, even
34561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * registers that "should" only need to be set once at boot, so that
34571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * there is non-reboot way to recover if something goes wrong.
34581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
34591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_open(struct net_device *dev)
34601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
34611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
34621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
34641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_open\n", dev->name);
34651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_init_adapter(dev);
34671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(err < 0)
3468807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
34691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3470807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
34711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
34721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Interrupt driven open of Token card. */
34741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_open_tr(struct net_device *dev)
34751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
34761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
34771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned long flags;
34781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
34791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
34811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_open_tr\n", dev->name);
34821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Now we can actually open the adapter. */
34841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->status == OPEN)
3485807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return 0;
34861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->status != INITIALIZED)
3487807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return -1;
34881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* FIXME: it would work a lot better if we masked the irq sources
34901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	   on the card here, then we could skip the locking and poll nicely */
34911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&tp->lock, flags);
34921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_page(dev, (__u8 *)tp->ram_access);
34941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)MAC_QUEUE)))
34961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                goto out;
34971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
34981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)MAC_QUEUE)))
34991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                goto out;
35001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)NON_MAC_QUEUE)))
35021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                goto out;
35031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)NON_MAC_QUEUE)))
35051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                goto out;
35061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->status = CLOSED;
35081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Insert into the Ring or Enter Loopback Mode. */
35101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((tp->mode_bits & LOOPING_MODE_MASK) == LOOPBACK_MODE_1)
35111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
35121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->status = CLOSED;
35131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(!(err = smctr_issue_trc_loopback_cmd(dev)))
35151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
35161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(!(err = smctr_wait_cmd(dev)))
35171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                tp->status = OPEN;
35181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
35191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_status_chg(dev);
35211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
35221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
35231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
35241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if((tp->mode_bits & LOOPING_MODE_MASK) == LOOPBACK_MODE_2)
35251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
35261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->status = CLOSED;
35271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(!(err = smctr_issue_tri_loopback_cmd(dev)))
35281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        {
35291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(!(err = smctr_wait_cmd(dev)))
35301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        tp->status = OPEN;
35311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        }
35321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        smctr_status_chg(dev);
35341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
35351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
35361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
35371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if((tp->mode_bits & LOOPING_MODE_MASK)
35381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                == LOOPBACK_MODE_3)
35391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        {
35401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                tp->status = CLOSED;
35411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(!(err = smctr_lobe_media_test_cmd(dev)))
35421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
35431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(!(err = smctr_wait_cmd(dev)))
35441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                tp->status = OPEN;
35451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
35461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                smctr_status_chg(dev);
35471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        }
35481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        else
35491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        {
35501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(!(err = smctr_lobe_media_test(dev)))
35511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        err = smctr_issue_insert_cmd(dev);
35521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				else
35531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
35541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(err == LOBE_MEDIA_TEST_FAILED)
35551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                printk(KERN_WARNING "%s: Lobe Media Test Failure - Check cable?\n", dev->name);
35561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
35571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        }
35581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
35591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
35601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
35621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        spin_unlock_irqrestore(&tp->lock, flags);
35631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3564807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
35651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
35661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Check for a network adapter of this type,
35681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * and return device structure if one exists.
35691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
35701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct net_device __init *smctr_probe(int unit)
35711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
35721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *dev = alloc_trdev(sizeof(struct net_local));
35731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	static const unsigned ports[] = {
35741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x200, 0x220, 0x240, 0x260, 0x280, 0x2A0, 0x2C0, 0x2E0, 0x300,
35751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		0x320, 0x340, 0x360, 0x380, 0
35761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	};
35771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const unsigned *port;
35781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err = 0;
35791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev)
35811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(-ENOMEM);
35821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (unit >= 0) {
35841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sprintf(dev->name, "tr%d", unit);
35851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		netdev_boot_setup_check(dev);
35861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
35871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if (dev->base_addr > 0x1ff)    /* Check a single specified location. */
35891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = smctr_probe1(dev, dev->base_addr);
35901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else if(dev->base_addr != 0)  /* Don't probe at all. */
35911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                err =-ENXIO;
35921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
35931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		for (port = ports; *port; port++) {
35941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = smctr_probe1(dev, *port);
35951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!err)
35961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				break;
35971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
35981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
35991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
36001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
36011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = register_netdev(dev);
36021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
36031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out1;
36041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return dev;
36051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout1:
36061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_MCA_LEGACY
36071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ struct net_local *tp = netdev_priv(dev);
36081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  if (tp->slot_num)
36091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mca_mark_as_unused(tp->slot_num);
36101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
36111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
36121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	release_region(dev->base_addr, SMCTR_IO_EXTENT);
36131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(dev->irq, dev);
36141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
36151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_netdev(dev);
36161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ERR_PTR(err);
36171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
36181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3619f70d59492ed8bc1d74b364ebe2b97ef6705910b1Stephen Hemmingerstatic const struct net_device_ops smctr_netdev_ops = {
3620f70d59492ed8bc1d74b364ebe2b97ef6705910b1Stephen Hemminger	.ndo_open          = smctr_open,
3621f70d59492ed8bc1d74b364ebe2b97ef6705910b1Stephen Hemminger	.ndo_stop          = smctr_close,
3622f70d59492ed8bc1d74b364ebe2b97ef6705910b1Stephen Hemminger	.ndo_start_xmit    = smctr_send_packet,
3623f70d59492ed8bc1d74b364ebe2b97ef6705910b1Stephen Hemminger	.ndo_tx_timeout	   = smctr_timeout,
3624f70d59492ed8bc1d74b364ebe2b97ef6705910b1Stephen Hemminger	.ndo_get_stats     = smctr_get_stats,
3625afc4b13df143122f99a0eb10bfefb216c2806de0Jiri Pirko	.ndo_set_rx_mode   = smctr_set_multicast_list,
3626f70d59492ed8bc1d74b364ebe2b97ef6705910b1Stephen Hemminger};
36271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init smctr_probe1(struct net_device *dev, int ioaddr)
36291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
36301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        static unsigned version_printed;
36311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
36321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err;
36331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u32 *ram;
36341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug && version_printed++ == 0)
36361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(version);
36371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        spin_lock_init(&tp->lock);
36391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        dev->base_addr = ioaddr;
36401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Actually detect an adapter now. */
36421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_chk_isa(dev);
36431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(err < 0)
36441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
36451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((err = smctr_chk_mca(dev)) < 0) {
36461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			err = -ENODEV;
36471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			goto out;
36481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
36491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
36501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp = netdev_priv(dev);
36521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        dev->mem_start = tp->ram_base;
36531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        dev->mem_end = dev->mem_start + 0x10000;
36541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        ram = (__u32 *)phys_to_virt(dev->mem_start);
36551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->ram_access = *(__u32 *)&ram;
36561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	tp->status = NOT_INITIALIZED;
36571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_load_firmware(dev);
36591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(err != UCODE_PRESENT && err != SUCCESS)
36601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
36611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_ERR "%s: Firmware load failed (%d)\n", dev->name, err);
36621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		err = -EIO;
36631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
36641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
36651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Allow user to specify ring speed on module insert. */
36671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(ringspeed == 4)
36681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tp->media_type = MEDIA_UTP_4;
36691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
36701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		tp->media_type = MEDIA_UTP_16;
36711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        printk(KERN_INFO "%s: %s %s at Io %#4x, Irq %d, Rom %#4x, Ram %#4x.\n",
36731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                dev->name, smctr_name, smctr_model,
36741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                (unsigned int)dev->base_addr,
36751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                dev->irq, tp->rom_base, tp->ram_base);
36761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3677f70d59492ed8bc1d74b364ebe2b97ef6705910b1Stephen Hemminger	dev->netdev_ops = &smctr_netdev_ops;
36781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        dev->watchdog_timeo	= HZ;
3679807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
36801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
36821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return err;
36831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
36841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
36861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_device *dev, __u16 rx_status)
36871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
36881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
36891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct sk_buff *skb;
36901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 rcode, correlator;
36911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err = 0;
36921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 xframe = 1;
36931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
36941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        rmf->vl = SWAP_BYTES(rmf->vl);
36951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(rx_status & FCB_RX_STATUS_DA_MATCHED)
36961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
36971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                switch(rmf->vc)
36981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
36991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Received MAC Frames Processed by RS. */
37001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case INIT:
37011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if((rcode = smctr_rcv_init(dev, rmf, &correlator)) == HARDWARE_FAILED)
37021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
3703807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                        return rcode;
37041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
37051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if((err = smctr_send_rsp(dev, rmf, rcode,
37071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        correlator)))
37081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
3709807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                        return err;
37101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
37111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
37121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case CHG_PARM:
37141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if((rcode = smctr_rcv_chg_param(dev, rmf,
37151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        &correlator)) ==HARDWARE_FAILED)
37161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
3717807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                        return rcode;
37181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
37191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if((err = smctr_send_rsp(dev, rmf, rcode,
37211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        correlator)))
37221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
3723807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                        return err;
37241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
37251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
37261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RQ_ADDR:
37281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if((rcode = smctr_rcv_rq_addr_state_attch(dev,
37291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        rmf, &correlator)) != POSITIVE_ACK)
37301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
37311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(rcode == HARDWARE_FAILED)
3732807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                return rcode;
37331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        else
3734807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                return smctr_send_rsp(dev, rmf,
3735807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                        rcode, correlator);
37361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
37371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if((err = smctr_send_rpt_addr(dev, rmf,
37391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        correlator)))
37401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
3741807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                        return err;
37421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
37431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
37441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RQ_ATTCH:
37461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if((rcode = smctr_rcv_rq_addr_state_attch(dev,
37471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        rmf, &correlator)) != POSITIVE_ACK)
37481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
37491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(rcode == HARDWARE_FAILED)
3750807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                return rcode;
37511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        else
3752807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                return smctr_send_rsp(dev, rmf,
37531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        rcode,
3754807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                        correlator);
37551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
37561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if((err = smctr_send_rpt_attch(dev, rmf,
37581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        correlator)))
37591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
3760807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                        return err;
37611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
37621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
37631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RQ_STATE:
37651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if((rcode = smctr_rcv_rq_addr_state_attch(dev,
37661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        rmf, &correlator)) != POSITIVE_ACK)
37671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
37681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(rcode == HARDWARE_FAILED)
3769807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                return rcode;
37701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        else
3771807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                return smctr_send_rsp(dev, rmf,
37721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        rcode,
3773807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                        correlator);
37741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
37751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if((err = smctr_send_rpt_state(dev, rmf,
37771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        correlator)))
37781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
3779807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                        return err;
37801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
37811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
37821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3783a6343afb6e16b65b9f0b264f94f8207212e7e3aeJeff Garzik                        case TX_FORWARD: {
3784a6343afb6e16b65b9f0b264f94f8207212e7e3aeJeff Garzik        			__u16 uninitialized_var(tx_fstatus);
3785a6343afb6e16b65b9f0b264f94f8207212e7e3aeJeff Garzik
37861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if((rcode = smctr_rcv_tx_forward(dev, rmf))
37871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        != POSITIVE_ACK)
37881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
37891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(rcode == HARDWARE_FAILED)
3790807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                return rcode;
37911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        else
3792807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                return smctr_send_rsp(dev, rmf,
37931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                        rcode,
3794807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                        correlator);
37951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
37961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
37971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if((err = smctr_send_tx_forward(dev, rmf,
37981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        &tx_fstatus)) == HARDWARE_FAILED)
37991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
3800807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                        return err;
38011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
38021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(err == A_FRAME_WAS_FORWARDED)
38041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
38051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((err = smctr_send_rpt_tx_forward(dev,
38061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						rmf, tx_fstatus))
38071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                == HARDWARE_FAILED)
38081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        {
3809807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                return err;
38101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        }
38111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
38121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
3813a6343afb6e16b65b9f0b264f94f8207212e7e3aeJeff Garzik			}
38141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Received MAC Frames Processed by CRS/REM/RPS. */
38161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RSP:
38171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RQ_INIT:
38181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_NEW_MON:
38191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_SUA_CHG:
38201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_ACTIVE_ERR:
38211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_NN_INCMP:
38221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_ERROR:
38231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_ATTCH:
38241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_STATE:
38251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_ADDR:
38261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
38271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* Rcvd Att. MAC Frame (if RXATMAC set) or UNKNOWN */
38291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        default:
38301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                xframe = 0;
38311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(!(tp->receive_mask & ACCEPT_ATT_MAC_FRAMES))
38321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
38331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        rcode = smctr_rcv_unknown(dev, rmf,
38341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                &correlator);
38351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if((err = smctr_send_rsp(dev, rmf,rcode,
38361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                correlator)))
38371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        {
3838807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                                return err;
38391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        }
38401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
38411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
38431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
38441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
38451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
38461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
38471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* 1. DA doesn't match (Promiscuous Mode).
38481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * 2. Parse for Extended MAC Frame Type.
38491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 */
38501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                switch(rmf->vc)
38511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
38521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RSP:
38531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case INIT:
38541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RQ_INIT:
38551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RQ_ADDR:
38561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RQ_ATTCH:
38571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RQ_STATE:
38581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case CHG_PARM:
38591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_ADDR:
38601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_ERROR:
38611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_ATTCH:
38621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_STATE:
38631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_NEW_MON:
38641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_SUA_CHG:
38651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_NN_INCMP:
38661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case RPT_ACTIVE_ERR:
38671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
38681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        default:
38701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                xframe = 0;
38711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
38721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
38731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
38741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* NOTE: UNKNOWN MAC frames will NOT be passed up unless
38761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * ACCEPT_ATT_MAC_FRAMES is set.
38771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
38788e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches        if(((tp->receive_mask & ACCEPT_ATT_MAC_FRAMES) &&
38798e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	    (xframe == (__u8)0)) ||
38808e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	   ((tp->receive_mask & ACCEPT_EXT_MAC_FRAMES) &&
38818e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	    (xframe == (__u8)1)))
38821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
38831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                rmf->vl = SWAP_BYTES(rmf->vl);
38841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if (!(skb = dev_alloc_skb(size)))
38861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ENOMEM;
38871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                skb->len = size;
38881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Slide data into a sleek skb. */
38901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                skb_put(skb, skb->len);
389127d7ff46a3498d3debc6ba68fb8014c702b81170Arnaldo Carvalho de Melo                skb_copy_to_linear_data(skb, rmf, skb->len);
38921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Update Counters */
38941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->MacStat.rx_packets++;
38951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->MacStat.rx_bytes += skb->len;
38961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
38971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Kick the packet on up. */
38981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                skb->protocol = tr_type_trans(skb, dev);
38991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                netif_rx(skb);
39001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                err = 0;
39011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
39021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3903807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
39041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
39051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Adapter RAM test. Incremental word ODD boundary data test. */
39071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_ram_memory_test(struct net_device *dev)
39081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
39091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
39101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 page, pages_of_ram, start_pattern = 0, word_pattern = 0,
39111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                word_read = 0, err_word = 0, err_pattern = 0;
39121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int err_offset;
39131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u32 j, pword;
39141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 err = 0;
39151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
39171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_ram_memory_test\n", dev->name);
39181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        start_pattern   = 0x0001;
39201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        pages_of_ram    = tp->ram_size / tp->ram_usable;
39211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        pword           = tp->ram_access;
39221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Incremental word ODD boundary test. */
39241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(page = 0; (page < pages_of_ram) && (~err);
39251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                page++, start_pattern += 0x8000)
39261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
39271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_set_page(dev, (__u8 *)(tp->ram_access
39281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        + (page * tp->ram_usable * 1024) + 1));
39291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                word_pattern = start_pattern;
39301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for(j = 1; j < (__u32)(tp->ram_usable * 1024) - 1; j += 2)
39321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        *(__u16 *)(pword + j) = word_pattern++;
39331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                word_pattern = start_pattern;
39351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39368e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches                for(j = 1; j < (__u32)(tp->ram_usable * 1024) - 1 && (~err);
39378e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches		    j += 2, word_pattern++)
39381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
39391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        word_read = *(__u16 *)(pword + j);
39401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(word_read != word_pattern)
39411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        {
39421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err             = (__u8)1;
39431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err_offset      = j;
39441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err_word        = word_read;
39451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err_pattern     = word_pattern;
3946807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                return RAM_TEST_FAILED;
39471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        }
39481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
39491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
39501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Zero out memory. */
39521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(page = 0; page < pages_of_ram && (~err); page++)
39531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
39541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_set_page(dev, (__u8 *)(tp->ram_access
39551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        + (page * tp->ram_usable * 1024)));
39561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                word_pattern = 0;
39571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                for(j = 0; j < (__u32)tp->ram_usable * 1024; j +=2)
39591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        *(__u16 *)(pword + j) = word_pattern;
39601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39618e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches                for(j =0; j < (__u32)tp->ram_usable * 1024 && (~err); j += 2)
39621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
39631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        word_read = *(__u16 *)(pword + j);
39641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(word_read != word_pattern)
39651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        {
39661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err             = (__u8)1;
39671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err_offset      = j;
39681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err_word        = word_read;
39691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                err_pattern     = word_pattern;
3970807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                                return RAM_TEST_FAILED;
39711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        }
39721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
39731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
39741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_set_page(dev, (__u8 *)tp->ram_access);
39761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3977807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
39781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
39791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
39811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 *correlator)
39821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
39831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv;
39841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        signed short vlen;
39851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 rcode = POSITIVE_ACK;
39861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
39871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* This Frame can only come from a CRS */
39891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((rmf->dc_sc & SC_MASK) != SC_CRS)
3990807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return E_INAPPROPRIATE_SOURCE_CLASS;
39911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Remove MVID Length from total length. */
39931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        vlen = (signed short)rmf->vl - 4;
39941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Point to First SVID */
39961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
39971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
39981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Search for Appropriate SVID's. */
39991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        while((vlen > 0) && (rcode == POSITIVE_ACK))
40001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
40011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                switch(rsv->svi)
40021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
40031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case CORRELATOR:
40041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                svectors |= F_CORRELATOR;
40051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = smctr_set_corr(dev, rsv, correlator);
40061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
40071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case LOCAL_RING_NUMBER:
40091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                svectors |= F_LOCAL_RING_NUMBER;
40101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = smctr_set_local_ring_num(dev, rsv);
40111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
40121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ASSIGN_PHYSICAL_DROP:
40141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                svectors |= F_ASSIGN_PHYSICAL_DROP;
40151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = smctr_set_phy_drop(dev, rsv);
40161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
40171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ERROR_TIMER_VALUE:
40191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                svectors |= F_ERROR_TIMER_VALUE;
40201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = smctr_set_error_timer_value(dev, rsv);
40211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
40221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case AUTHORIZED_FUNCTION_CLASS:
40241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                svectors |= F_AUTHORIZED_FUNCTION_CLASS;
40251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = smctr_set_auth_funct_class(dev, rsv);
40261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
40271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case AUTHORIZED_ACCESS_PRIORITY:
40291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                svectors |= F_AUTHORIZED_ACCESS_PRIORITY;
40301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = smctr_set_auth_access_pri(dev, rsv);
40311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
40321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        default:
40341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = E_SUB_VECTOR_UNKNOWN;
40351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
40361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
40371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Let Sender Know if SUM of SV length's is
40391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * larger then length in MVID length field
40401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 */
40411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if((vlen -= rsv->svl) < 0)
40421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        rcode = E_VECTOR_LENGTH_ERROR;
40431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
40451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
40461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(rcode == POSITIVE_ACK)
40481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
40491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Let Sender Know if MVID length field
40501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * is larger then SUM of SV length's
40511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 */
40521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(vlen != 0)
40531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        rcode = E_VECTOR_LENGTH_ERROR;
40541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
40551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
40561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                	/* Let Sender Know if Expected SVID Missing */
40571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                	if((svectors & R_CHG_PARM) ^ R_CHG_PARM)
40581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        	rcode = E_MISSING_SUB_VECTOR;
40591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
40601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
40611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4062807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return rcode;
40631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
40641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_rcv_init(struct net_device *dev, MAC_HEADER *rmf,
40661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 *correlator)
40671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
40681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv;
40691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        signed short vlen;
40701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 rcode = POSITIVE_ACK;
40711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
40721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* This Frame can only come from a RPS */
40741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((rmf->dc_sc & SC_MASK) != SC_RPS)
4075807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return E_INAPPROPRIATE_SOURCE_CLASS;
40761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Remove MVID Length from total length. */
40781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        vlen = (signed short)rmf->vl - 4;
40791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Point to First SVID */
40811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
40821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Search for Appropriate SVID's */
40841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        while((vlen > 0) && (rcode == POSITIVE_ACK))
40851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
40861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                switch(rsv->svi)
40871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
40881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case CORRELATOR:
40891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                svectors |= F_CORRELATOR;
40901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = smctr_set_corr(dev, rsv, correlator);
40911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
40921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case LOCAL_RING_NUMBER:
40941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                svectors |= F_LOCAL_RING_NUMBER;
40951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = smctr_set_local_ring_num(dev, rsv);
40961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
40971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
40981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ASSIGN_PHYSICAL_DROP:
40991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                svectors |= F_ASSIGN_PHYSICAL_DROP;
41001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = smctr_set_phy_drop(dev, rsv);
41011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
41021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case ERROR_TIMER_VALUE:
41041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                svectors |= F_ERROR_TIMER_VALUE;
41051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = smctr_set_error_timer_value(dev, rsv);
41061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
41071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        default:
41091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = E_SUB_VECTOR_UNKNOWN;
41101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
41111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
41121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Let Sender Know if SUM of SV length's is
41141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * larger then length in MVID length field
41151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
41161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if((vlen -= rsv->svl) < 0)
41171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        rcode = E_VECTOR_LENGTH_ERROR;
41181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
41201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
41211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(rcode == POSITIVE_ACK)
41231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
41241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Let Sender Know if MVID length field
41251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * is larger then SUM of SV length's
41261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 */
41271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(vlen != 0)
41281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        rcode = E_VECTOR_LENGTH_ERROR;
41291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
41301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
41311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                	/* Let Sender Know if Expected SV Missing */
41321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                	if((svectors & R_INIT) ^ R_INIT)
41331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        	rcode = E_MISSING_SUB_VECTOR;
41341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
41351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
41361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4137807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return rcode;
41381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
41391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_rcv_tx_forward(struct net_device *dev, MAC_HEADER *rmf)
41411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
41421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv;
41431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        signed short vlen;
41441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 rcode = POSITIVE_ACK;
41451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
41461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* This Frame can only come from a CRS */
41481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((rmf->dc_sc & SC_MASK) != SC_CRS)
4149807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return E_INAPPROPRIATE_SOURCE_CLASS;
41501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Remove MVID Length from total length */
41521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        vlen = (signed short)rmf->vl - 4;
41531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Point to First SVID */
41551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
41561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Search for Appropriate SVID's */
41581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        while((vlen > 0) && (rcode == POSITIVE_ACK))
41591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
41601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                switch(rsv->svi)
41611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
41621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case FRAME_FORWARD:
41631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                svectors |= F_FRAME_FORWARD;
41641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = smctr_set_frame_forward(dev, rsv,
41651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					rmf->dc_sc);
41661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
41671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        default:
41691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = E_SUB_VECTOR_UNKNOWN;
41701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
41711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
41721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Let Sender Know if SUM of SV length's is
41741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * larger then length in MVID length field
41751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
41761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if((vlen -= rsv->svl) < 0)
41771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        rcode = E_VECTOR_LENGTH_ERROR;
41781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
41801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
41811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
41821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(rcode == POSITIVE_ACK)
41831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
41841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Let Sender Know if MVID length field
41851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * is larger then SUM of SV length's
41861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 */
41871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(vlen != 0)
41881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        rcode = E_VECTOR_LENGTH_ERROR;
41891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
41901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
41911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                	/* Let Sender Know if Expected SV Missing */
41921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                	if((svectors & R_TX_FORWARD) ^ R_TX_FORWARD)
41931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        	rcode = E_MISSING_SUB_VECTOR;
41941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
41951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
41961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4197807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return rcode;
41981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
41991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_rcv_rq_addr_state_attch(struct net_device *dev,
42011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_HEADER *rmf, __u16 *correlator)
42021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
42031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv;
42041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        signed short vlen;
42051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 rcode = POSITIVE_ACK;
42061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int svectors = F_NO_SUB_VECTORS_FOUND;
42071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Remove MVID Length from total length */
42091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        vlen = (signed short)rmf->vl - 4;
42101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Point to First SVID */
42121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
42131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Search for Appropriate SVID's */
42151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        while((vlen > 0) && (rcode == POSITIVE_ACK))
42161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
42171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                switch(rsv->svi)
42181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
42191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case CORRELATOR:
42201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                svectors |= F_CORRELATOR;
42211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = smctr_set_corr(dev, rsv, correlator);
42221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
42231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        default:
42251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                rcode = E_SUB_VECTOR_UNKNOWN;
42261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
42271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
42281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Let Sender Know if SUM of SV length's is
42301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * larger then length in MVID length field
42311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 */
42321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if((vlen -= rsv->svl) < 0)
42331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        rcode = E_VECTOR_LENGTH_ERROR;
42341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
42361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
42371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(rcode == POSITIVE_ACK)
42391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
42401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Let Sender Know if MVID length field
42411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * is larger then SUM of SV length's
42421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 */
42431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(vlen != 0)
42441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        rcode = E_VECTOR_LENGTH_ERROR;
42451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
42461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
42471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                	/* Let Sender Know if Expected SVID Missing */
42481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                	if((svectors & R_RQ_ATTCH_STATE_ADDR)
42491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				^ R_RQ_ATTCH_STATE_ADDR)
42501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        	rcode = E_MISSING_SUB_VECTOR;
42511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
42521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
42531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4254807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return rcode;
42551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
42561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_rcv_unknown(struct net_device *dev, MAC_HEADER *rmf,
42581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 *correlator)
42591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
42601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv;
42611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        signed short vlen;
42621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *correlator = 0;
42641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Remove MVID Length from total length */
42661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        vlen = (signed short)rmf->vl - 4;
42671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Point to First SVID */
42691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        rsv = (MAC_SUB_VECTOR *)((__u32)rmf + sizeof(MAC_HEADER));
42701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Search for CORRELATOR for RSP to UNKNOWN */
42721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        while((vlen > 0) && (*correlator == 0))
42731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
42741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                switch(rsv->svi)
42751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
42761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        case CORRELATOR:
42771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                smctr_set_corr(dev, rsv, correlator);
42781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
42791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        default:
42811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
42821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
42831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                vlen -= rsv->svl;
42851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                rsv = (MAC_SUB_VECTOR *)((__u32)rsv + rsv->svl);
42861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
42871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4288807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return E_UNRECOGNIZED_VECTOR_ID;
42891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
42901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
42911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
42921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Reset the 825 NIC and exit w:
42931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1. The NIC reset cleared (non-reset state), halted and un-initialized.
42941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2. TINT masked.
42951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 3. CBUSY masked.
42961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4. TINT clear.
42971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5. CBUSY clear.
42981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
42991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_reset_adapter(struct net_device *dev)
43001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
43011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
43021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ioaddr = dev->base_addr;
43031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Reseting the NIC will put it in a halted and un-initialized state. */        smctr_set_trc_reset(ioaddr);
43051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mdelay(200); /* ~2 ms */
43061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_clear_trc_reset(ioaddr);
43081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        mdelay(200); /* ~2 ms */
43091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Remove any latched interrupts that occurred prior to reseting the
43111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * adapter or possibily caused by line glitches due to the reset.
43121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
43131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(tp->trc_mask | CSR_CLRTINT | CSR_CLRCBUSY, ioaddr + CSR);
43141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4315807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
43161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
43171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_restart_tx_chain(struct net_device *dev, short queue)
43191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
43201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
43211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err = 0;
43221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
43241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_restart_tx_chain\n", dev->name);
43251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43268e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches        if(tp->num_tx_fcbs_used[queue] != 0 &&
43278e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	   tp->tx_queue_status[queue] == NOT_TRANSMITING)
43281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
43291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->tx_queue_status[queue] = TRANSMITING;
43301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                err = smctr_issue_resume_tx_fcb_cmd(dev, queue);
43311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
43321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4333807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
43341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
43351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_ring_status_chg(struct net_device *dev)
43371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
43381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
43391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
43411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_ring_status_chg\n", dev->name);
43421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Check for ring_status_flag: whenever MONITOR_STATE_BIT
43441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * Bit is set, check value of monitor_state, only then we
43451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * enable and start transmit/receive timeout (if and only
43461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * if it is MS_ACTIVE_MONITOR_STATE or MS_STANDBY_MONITOR_STATE)
43471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
43481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->ring_status_flags == MONITOR_STATE_CHANGED)
43491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
43508e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches                if((tp->monitor_state == MS_ACTIVE_MONITOR_STATE) ||
43518e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches		   (tp->monitor_state == MS_STANDBY_MONITOR_STATE))
43521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
43531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->monitor_state_ready = 1;
43541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
43551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
43561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
43571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* if adapter is NOT in either active monitor
43581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         * or standby monitor state => Disable
43591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         * transmit/receive timeout.
43601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                         */
43611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->monitor_state_ready = 0;
43621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			/* Ring speed problem, switching to auto mode. */
43648e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches			if(tp->monitor_state == MS_MONITOR_FSM_INACTIVE &&
43658e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches			   !tp->cleanup)
43661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			{
43671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				printk(KERN_INFO "%s: Incorrect ring speed switching.\n",
43681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dev->name);
43691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				smctr_set_ring_speed(dev);
43701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
43711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
43721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
43731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(!(tp->ring_status_flags & RING_STATUS_CHANGED))
4375807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return 0;
43761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        switch(tp->ring_status)
43781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
43791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case RING_RECOVERY:
43801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_INFO "%s: Ring Recovery\n", dev->name);
43811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
43821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case SINGLE_STATION:
43841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_INFO "%s: Single Statinon\n", dev->name);
43851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
43861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case COUNTER_OVERFLOW:
43881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_INFO "%s: Counter Overflow\n", dev->name);
43891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
43901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case REMOVE_RECEIVED:
43921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_INFO "%s: Remove Received\n", dev->name);
43931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
43941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case AUTO_REMOVAL_ERROR:
43961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_INFO "%s: Auto Remove Error\n", dev->name);
43971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
43981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
43991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case LOBE_WIRE_FAULT:
44001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_INFO "%s: Lobe Wire Fault\n", dev->name);
44011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
44021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case TRANSMIT_BEACON:
44041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_INFO "%s: Transmit Beacon\n", dev->name);
44051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
44061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case SOFT_ERROR:
44081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_INFO "%s: Soft Error\n", dev->name);
44091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
44101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case HARD_ERROR:
44121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_INFO "%s: Hard Error\n", dev->name);
44131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
44141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case SIGNAL_LOSS:
44161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_INFO "%s: Signal Loss\n", dev->name);
44171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
44181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                default:
44201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_INFO "%s: Unknown ring status change\n",
44211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dev->name);
44221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
44231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
44241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4425807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
44261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
44271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_rx_frame(struct net_device *dev)
44291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
44301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
44311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 queue, status, rx_size, err = 0;
44321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 *pbuff;
44331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
44351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_rx_frame\n", dev->name);
44361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        queue = tp->receive_queue_number;
44381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        while((status = tp->rx_fcb_curr[queue]->frame_status) != SUCCESS)
44401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
44411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                err = HARDWARE_FAILED;
44421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44438e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches                if(((status & 0x007f) == 0) ||
44448e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches		   ((tp->receive_mask & ACCEPT_ERR_PACKETS) != 0))
44451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
44461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* frame length less the CRC (4 bytes) + FS (1 byte) */
44471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        rx_size = tp->rx_fcb_curr[queue]->frame_length - 5;
44481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        pbuff = smctr_get_rx_pointer(dev, queue);
44501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        smctr_set_page(dev, pbuff);
44521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        smctr_disable_16bit(dev);
44531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        /* pbuff points to addr within one page */
44551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        pbuff = (__u8 *)PAGE_POINTER(pbuff);
44561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(queue == NON_MAC_QUEUE)
44581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        {
44591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                struct sk_buff *skb;
44601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                skb = dev_alloc_skb(rx_size);
44621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (skb) {
44631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                	skb_put(skb, rx_size);
44641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
446527d7ff46a3498d3debc6ba68fb8014c702b81170Arnaldo Carvalho de Melo					skb_copy_to_linear_data(skb, pbuff, rx_size);
44661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                	/* Update Counters */
44681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                	tp->MacStat.rx_packets++;
44691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                	tp->MacStat.rx_bytes += skb->len;
44701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                	/* Kick the packet on up. */
44721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                	skb->protocol = tr_type_trans(skb, dev);
44731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                	netif_rx(skb);
44741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else {
44751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
44761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        }
44771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        else
44781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                smctr_process_rx_packet((MAC_HEADER *)pbuff,
44791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        rx_size, dev, status);
44801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
44811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_enable_16bit(dev);
44831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_set_page(dev, (__u8 *)tp->ram_access);
44841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_update_rx_chain(dev, queue);
44851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(err != SUCCESS)
44871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
44881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
44891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4490807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
44911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
44921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_dat(struct net_device *dev)
44941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
44951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
44961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i, err;
44971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_HEADER *tmf;
44981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
44991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
45011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_send_dat\n", dev->name);
45021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE,
45041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                sizeof(MAC_HEADER))) == (FCBlock *)(-1L))
45051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
4506807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return OUT_OF_RESOURCES;
45071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
45081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize DAT Data Fields. */
45101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
45111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->ac = MSB(AC_FC_DAT);
45121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->fc = LSB(AC_FC_DAT);
45131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < 6; i++)
45151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
45161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tmf->sa[i] = dev->dev_addr[i];
45171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tmf->da[i] = dev->dev_addr[i];
45181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
45201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vc        = DAT;
45221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->dc_sc     = DC_RS | SC_RS;
45231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl        = 4;
45241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl        = SWAP_BYTES(tmf->vl);
45251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Start Transmit. */
45271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
4528807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
45291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Wait for Transmit to Complete */
45311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < 10000; i++)
45321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
45331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(fcb->frame_status & FCB_COMMAND_DONE)
45341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
45351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                mdelay(1);
45361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
45371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Check if GOOD frame Tx'ed. */
45398e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches        if(!(fcb->frame_status &  FCB_COMMAND_DONE) ||
45408e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	   fcb->frame_status & (FCB_TX_STATUS_E | FCB_TX_AC_BITS))
45411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
4542807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return INITIALIZE_FAILED;
45431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
45441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* De-allocated Tx FCB and Frame Buffer
45461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * The FCB must be de-allocated manually if executing with
45471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * interrupts disabled, other wise the ISR (LM_Service_Events)
45481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * will de-allocate it when the interrupt occurs.
45491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
45501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
45511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
45521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4553807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
45541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
45551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void smctr_timeout(struct net_device *dev)
45571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
45581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
45591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * If we get here, some higher level has decided we are broken.
45601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * There should really be a "kick me" function call instead.
45611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         *
45621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * Resetting the token ring adapter takes a long time so just
45631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * fake transmission time and go on trying. Our own timeout
45641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * routine is in sktr_timer_chk()
45651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
45661ae5dc342ac78d7a42965fd1f323815f6f5ef2c1Eric Dumazet        dev->trans_start = jiffies; /* prevent tx timeout */
45671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        netif_wake_queue(dev);
45681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
45691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
45711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Gets skb from system, queues it and checks if it can be sent
45721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
457361a84108547c1c017683f15311ccbede249fc6faStephen Hemmingerstatic netdev_tx_t smctr_send_packet(struct sk_buff *skb,
457461a84108547c1c017683f15311ccbede249fc6faStephen Hemminger					   struct net_device *dev)
45751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
45761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
45771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
45791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_send_packet\n", dev->name);
45801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /*
45821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * Block a transmit overlap
45831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
45841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        netif_stop_queue(dev);
45861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->QueueSkb == 0)
45885b548140225c6bbbbd560551dd1048b2c0ce58bePatrick McHardy                return NETDEV_TX_BUSY;     /* Return with tbusy set: queue full */
45891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->QueueSkb--;
45911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        skb_queue_tail(&tp->SendSkbQueue, skb);
45921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_hardware_send_packet(dev, tp);
45931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->QueueSkb > 0)
45941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		netif_wake_queue(dev);
45951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4596ec634fe328182a1a098585bfc7b69e5042bdb08dPatrick McHardy        return NETDEV_TX_OK;
45971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
45981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
45991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_lobe_media_test(struct net_device *dev)
46001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
46011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
46021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MAC_SUB_VECTOR *tsv;
46031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	MAC_HEADER *tmf;
46041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
46051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u32 i;
46061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
46071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 15)
46091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_send_lobe_media_test\n", dev->name);
46101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(struct trh_hdr)
46121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                + S_WRAP_DATA + S_WRAP_DATA)) == (FCBlock *)(-1L))
46131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
4614807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return OUT_OF_RESOURCES;
46151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
46161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Initialize DAT Data Fields. */
46181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
46191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->ac = MSB(AC_FC_LOBE_MEDIA_TEST);
46201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->fc = LSB(AC_FC_LOBE_MEDIA_TEST);
46211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < 6; i++)
46231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
46241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tmf->da[i] = 0;
46251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tmf->sa[i] = dev->dev_addr[i];
46261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
46271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vc        = LOBE_MEDIA_TEST;
46291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->dc_sc     = DC_RS | SC_RS;
46301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl        = 4;
46311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
46331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_wrap_data(dev, tsv);
46341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
46351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
46371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_wrap_data(dev, tsv);
46381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
46391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Start Transmit. */
46411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl = SWAP_BYTES(tmf->vl);
46421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
4643807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
46441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Wait for Transmit to Complete. (10 ms). */
46461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i=0; i < 10000; i++)
46471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
46481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(fcb->frame_status & FCB_COMMAND_DONE)
46491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
46501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                mdelay(1);
46511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
46521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Check if GOOD frame Tx'ed */
46548e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches        if(!(fcb->frame_status & FCB_COMMAND_DONE) ||
46558e95a2026f3b43f7c3d676adaccd2de9532e8dccJoe Perches	   fcb->frame_status & (FCB_TX_STATUS_E | FCB_TX_AC_BITS))
46561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
4657807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return LOBE_MEDIA_TEST_FAILED;
46581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
46591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* De-allocated Tx FCB and Frame Buffer
46611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * The FCB must be de-allocated manually if executing with
46621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * interrupts disabled, other wise the ISR (LM_Service_Events)
46631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * will de-allocate it when the interrupt occurs.
46641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
46651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
46661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
46671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4668807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
46691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
46701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_rpt_addr(struct net_device *dev, MAC_HEADER *rmf,
46721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 correlator)
46731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
46741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_HEADER *tmf;
46751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv;
46761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
46771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
46791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		+ S_CORRELATOR + S_PHYSICAL_DROP + S_UPSTREAM_NEIGHBOR_ADDRESS
46801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		+ S_ADDRESS_MODIFER + S_GROUP_ADDRESS + S_FUNCTIONAL_ADDRESS))
46811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		== (FCBlock *)(-1L))
46821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
4683807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return 0;
46841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
46851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf 		= (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
46871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vc    	= RPT_ADDR;
46881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->dc_sc 	= (rmf->dc_sc & SC_MASK) << 4;
46891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl    	= 4;
46901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_ADDR);
46921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
46941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_corr(dev, tsv, correlator);
46951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
46961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
46971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
46981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_phy_drop_num(dev, tsv);
46991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
47011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
47021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_upstream_neighbor_addr(dev, tsv);
47031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
47051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
47061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_addr_mod(dev, tsv);
47071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
47091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
47101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_group_addr(dev, tsv);
47111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
47131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
47141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_funct_addr(dev, tsv);
47151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
47171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Subtract out MVID and MVL which is
47191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * include in both vl and MAC_HEADER
47201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
47211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*      fcb->frame_length           = tmf->vl + sizeof(MAC_HEADER) - 4;
47221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
47231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
47241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl = SWAP_BYTES(tmf->vl);
47251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4726807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return smctr_trc_send_packet(dev, fcb, MAC_QUEUE);
47271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
47281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_rpt_attch(struct net_device *dev, MAC_HEADER *rmf,
47301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 correlator)
47311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
47321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_HEADER *tmf;
47331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv;
47341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
47351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
47371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		+ S_CORRELATOR + S_PRODUCT_INSTANCE_ID + S_FUNCTIONAL_ADDRESS
47381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		+ S_AUTHORIZED_FUNCTION_CLASS + S_AUTHORIZED_ACCESS_PRIORITY))
47391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		== (FCBlock *)(-1L))
47401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
4741807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return 0;
47421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
47431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
47451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vc    = RPT_ATTCH;
47461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
47471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl    = 4;
47481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_ATTCH);
47501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
47521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_corr(dev, tsv, correlator);
47531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
47551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
47561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_product_id(dev, tsv);
47571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
47591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
47601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_funct_addr(dev, tsv);
47611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
47631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
47641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_auth_funct_class(dev, tsv);
47651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
47671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
47681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_access_pri(dev, tsv);
47691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
47711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Subtract out MVID and MVL which is
47731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * include in both vl and MAC_HEADER
47741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
47751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*      fcb->frame_length           = tmf->vl + sizeof(MAC_HEADER) - 4;
47761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
47771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
47781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl = SWAP_BYTES(tmf->vl);
47791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4780807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return smctr_trc_send_packet(dev, fcb, MAC_QUEUE);
47811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
47821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_rpt_state(struct net_device *dev, MAC_HEADER *rmf,
47841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 correlator)
47851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
47861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_HEADER *tmf;
47871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv;
47881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
47891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
47911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		+ S_CORRELATOR + S_RING_STATION_VERSION_NUMBER
47921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		+ S_RING_STATION_STATUS + S_STATION_IDENTIFER))
47931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		== (FCBlock *)(-1L))
47941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
4795807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return 0;
47961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
47971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
47981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
47991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vc    = RPT_STATE;
48001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
48011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl    = 4;
48021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_STATE);
48041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
48061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_corr(dev, tsv, correlator);
48071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
48091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
48101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_ring_station_version(dev, tsv);
48111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
48131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
48141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_ring_station_status(dev, tsv);
48151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
48171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
48181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_station_id(dev, tsv);
48191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
48211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Subtract out MVID and MVL which is
48231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * include in both vl and MAC_HEADER
48241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
48251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*      fcb->frame_length           = tmf->vl + sizeof(MAC_HEADER) - 4;
48261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
48271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
48281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl = SWAP_BYTES(tmf->vl);
48291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4830807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return smctr_trc_send_packet(dev, fcb, MAC_QUEUE);
48311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
48321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_rpt_tx_forward(struct net_device *dev,
48341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_HEADER *rmf, __u16 tx_fstatus)
48351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
48361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_HEADER *tmf;
48371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv;
48381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
48391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
48411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		+ S_TRANSMIT_STATUS_CODE)) == (FCBlock *)(-1L))
48421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
4843807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return 0;
48441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
48451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
48471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vc    = RPT_TX_FORWARD;
48481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
48491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl    = 4;
48501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RPT_TX_FORWARD);
48521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
48541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_tx_status_code(dev, tsv, tx_fstatus);
48551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl += tsv->svl;
48571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Subtract out MVID and MVL which is
48591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * include in both vl and MAC_HEADER
48601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
48611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*      fcb->frame_length           = tmf->vl + sizeof(MAC_HEADER) - 4;
48621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
48631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
48641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl = SWAP_BYTES(tmf->vl);
48651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4866807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return smctr_trc_send_packet(dev, fcb, MAC_QUEUE);
48671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
48681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_rsp(struct net_device *dev, MAC_HEADER *rmf,
48701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 rcode, __u16 correlator)
48711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
48721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_HEADER *tmf;
48731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv;
48741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
48751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
48771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		+ S_CORRELATOR + S_RESPONSE_CODE)) == (FCBlock *)(-1L))
48781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
4879807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return 0;
48801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
48811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
48831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vc    = RSP;
48841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->dc_sc = (rmf->dc_sc & SC_MASK) << 4;
48851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tmf->vl    = 4;
48861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_8025_hdr(dev, rmf, tmf, AC_FC_RSP);
48881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
48901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_make_corr(dev, tsv, correlator);
48911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4892807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
48931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
48941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
48951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_rq_init(struct net_device *dev)
48961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
48971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
48981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_HEADER *tmf;
48991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *tsv;
49001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
49011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned int i, count = 0;
49021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u16 fstatus;
49031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
49041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        do {
49061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	if(((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, sizeof(MAC_HEADER)
49071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			+ S_PRODUCT_INSTANCE_ID + S_UPSTREAM_NEIGHBOR_ADDRESS
49081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			+ S_RING_STATION_VERSION_NUMBER + S_ADDRESS_MODIFER))
49091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			== (FCBlock *)(-1L)))
49101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
4911807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                        return 0;
49121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
49131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tmf 	   = (MAC_HEADER *)fcb->bdb_ptr->data_block_ptr;
49151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tmf->vc    = RQ_INIT;
49161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tmf->dc_sc = DC_RPS | SC_RS;
49171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tmf->vl    = 4;
49181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_make_8025_hdr(dev, NULL, tmf, AC_FC_RQ_INIT);
49201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tsv = (MAC_SUB_VECTOR *)((__u32)tmf + sizeof(MAC_HEADER));
49221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_make_product_id(dev, tsv);
49231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tmf->vl += tsv->svl;
49251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
49261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_make_upstream_neighbor_addr(dev, tsv);
49271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tmf->vl += tsv->svl;
49291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
49301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_make_ring_station_version(dev, tsv);
49311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tmf->vl += tsv->svl;
49331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tsv = (MAC_SUB_VECTOR *)((__u32)tsv + tsv->svl);
49341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_make_addr_mod(dev, tsv);
49351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tmf->vl += tsv->svl;
49371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Subtract out MVID and MVL which is
49391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * include in both vl and MAC_HEADER
49401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 */
49411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*              fcb->frame_length           = tmf->vl + sizeof(MAC_HEADER) - 4;
49421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->bdb_ptr->buffer_length = tmf->vl + sizeof(MAC_HEADER) - 4;
49431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
49441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tmf->vl = SWAP_BYTES(tmf->vl);
49451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
4947807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                        return err;
49481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Wait for Transmit to Complete */
49501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      		for(i = 0; i < 10000; i++)
49511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
49521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          		if(fcb->frame_status & FCB_COMMAND_DONE)
49531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              			break;
49541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          		mdelay(1);
49551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      		}
49561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Check if GOOD frame Tx'ed */
49581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fstatus = fcb->frame_status;
49591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(!(fstatus & FCB_COMMAND_DONE))
4961807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                        return HARDWARE_FAILED;
49621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(!(fstatus & FCB_TX_STATUS_E))
49641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        count++;
49651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* De-allocated Tx FCB and Frame Buffer
49671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * The FCB must be de-allocated manually if executing with
49681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * interrupts disabled, other wise the ISR (LM_Service_Events)
49691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * will de-allocate it when the interrupt occurs.
49701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 */
49711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->tx_queue_status[MAC_QUEUE] = NOT_TRANSMITING;
49721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_update_tx_chain(dev, fcb, MAC_QUEUE);
49731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        } while(count < 4 && ((fstatus & FCB_TX_AC_BITS) ^ FCB_TX_AC_BITS));
49741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4975807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return smctr_join_complete_state(dev);
49761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
49771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_send_tx_forward(struct net_device *dev, MAC_HEADER *rmf,
49791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 *tx_fstatus)
49801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
49811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
49821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
49831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int i;
49841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
49851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Check if this is the END POINT of the Transmit Forward Chain. */
49871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(rmf->vl <= 18)
4988807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return 0;
49891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Allocate Transmit FCB only by requesting 0 bytes
49911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * of data buffer.
49921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
49931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((fcb = smctr_get_tx_fcb(dev, MAC_QUEUE, 0)) == (FCBlock *)(-1L))
4994807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return 0;
49951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
49961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Set pointer to Transmit Frame Buffer to the data
49971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * portion of the received TX Forward frame, making
49981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * sure to skip over the Vector Code (vc) and Vector
49991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         * length (vl).
50001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds         */
50011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fcb->bdb_ptr->trc_data_block_ptr = TRC_POINTER((__u32)rmf
50021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		+ sizeof(MAC_HEADER) + 2);
50031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fcb->bdb_ptr->data_block_ptr     = (__u16 *)((__u32)rmf
50041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		+ sizeof(MAC_HEADER) + 2);
50051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fcb->frame_length                = rmf->vl - 4 - 2;
50071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fcb->bdb_ptr->buffer_length      = rmf->vl - 4 - 2;
50081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_trc_send_packet(dev, fcb, MAC_QUEUE)))
5010807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
50111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Wait for Transmit to Complete */
50131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   	for(i = 0; i < 10000; i++)
50141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{
50151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds       		if(fcb->frame_status & FCB_COMMAND_DONE)
50161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds           		break;
50171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        	mdelay(1);
50181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds   	}
50191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Check if GOOD frame Tx'ed */
50211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(!(fcb->frame_status & FCB_COMMAND_DONE))
50221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
50231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if((err = smctr_issue_resume_tx_fcb_cmd(dev, MAC_QUEUE)))
5024807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                        return err;
50251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      		for(i = 0; i < 10000; i++)
50271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		{
50281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds          		if(fcb->frame_status & FCB_COMMAND_DONE)
50291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds              			break;
50301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        		mdelay(1);
50311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds      		}
50321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(!(fcb->frame_status & FCB_COMMAND_DONE))
5034807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                        return HARDWARE_FAILED;
50351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
50361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *tx_fstatus = fcb->frame_status;
50381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5039807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return A_FRAME_WAS_FORWARDED;
50401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
50411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_auth_access_pri(struct net_device *dev,
50431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv)
50441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
50451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
50461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(rsv->svl != S_AUTHORIZED_ACCESS_PRIORITY)
5048807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return E_SUB_VECTOR_LENGTH_ERROR;
50491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->authorized_access_priority = (rsv->svv[0] << 8 | rsv->svv[1]);
50511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5052807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return POSITIVE_ACK;
50531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
50541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_auth_funct_class(struct net_device *dev,
50561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv)
50571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
50581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
50591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(rsv->svl != S_AUTHORIZED_FUNCTION_CLASS)
5061807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return E_SUB_VECTOR_LENGTH_ERROR;
50621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->authorized_function_classes = (rsv->svv[0] << 8 | rsv->svv[1]);
50641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5065807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return POSITIVE_ACK;
50661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
50671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_corr(struct net_device *dev, MAC_SUB_VECTOR *rsv,
50691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 *correlator)
50701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
50711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(rsv->svl != S_CORRELATOR)
5072807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return E_SUB_VECTOR_LENGTH_ERROR;
50731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        *correlator = (rsv->svv[0] << 8 | rsv->svv[1]);
50751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5076807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return POSITIVE_ACK;
50771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
50781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_error_timer_value(struct net_device *dev,
50801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv)
50811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
50821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	__u16 err_tval;
50831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
50841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(rsv->svl != S_ERROR_TIMER_VALUE)
5086807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return E_SUB_VECTOR_LENGTH_ERROR;
50871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err_tval = (rsv->svv[0] << 8 | rsv->svv[1])*10;
50891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_issue_write_word_cmd(dev, RW_TER_THRESHOLD, &err_tval);
50911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_cmd(dev)))
5093807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
50941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5095807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return POSITIVE_ACK;
50961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
50971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
50981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_frame_forward(struct net_device *dev,
50991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv, __u8 dc_sc)
51001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
51011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((rsv->svl < 2) || (rsv->svl > S_FRAME_FORWARD))
5102807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return E_SUB_VECTOR_LENGTH_ERROR;
51031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((dc_sc & DC_MASK) != DC_CRS)
51051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
51061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(rsv->svl >= 2 && rsv->svl < 20)
5107807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet			return E_TRANSMIT_FORWARD_INVALID;
51081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if((rsv->svv[0] != 0) || (rsv->svv[1] != 0))
5110807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                        return E_TRANSMIT_FORWARD_INVALID;
51111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
51121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5113807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return POSITIVE_ACK;
51141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
51151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_local_ring_num(struct net_device *dev,
51171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        MAC_SUB_VECTOR *rsv)
51181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
51191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
51201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(rsv->svl != S_LOCAL_RING_NUMBER)
5122807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return E_SUB_VECTOR_LENGTH_ERROR;
51231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->ptr_local_ring_num)
51251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *(__u16 *)(tp->ptr_local_ring_num)
51261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			= (rsv->svv[0] << 8 | rsv->svv[1]);
51271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5128807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return POSITIVE_ACK;
51291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
51301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short smctr_set_ctrl_attention(struct net_device *dev)
51321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
51331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
51341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ioaddr = dev->base_addr;
51351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->bic_type == BIC_585_CHIP)
51371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                outb((tp->trc_mask | HWR_CA), ioaddr + HWR);
51381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
51391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
51401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                outb((tp->trc_mask | CSR_CA), ioaddr + CSR);
51411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                outb(tp->trc_mask, ioaddr + CSR);
51421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
51431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5144807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
51451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
51461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void smctr_set_multicast_list(struct net_device *dev)
51481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
51491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
51501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_set_multicast_list\n", dev->name);
51511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
51521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_page(struct net_device *dev, __u8 *buf)
51541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
51551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
51561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 amask;
51571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u32 tptr;
51581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tptr = (__u32)buf - (__u32)tp->ram_access;
51601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        amask = (__u8)((tptr & PR_PAGE_MASK) >> 8);
51611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(amask, dev->base_addr + PR);
51621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5163807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
51641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
51651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_phy_drop(struct net_device *dev, MAC_SUB_VECTOR *rsv)
51671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
51681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
51691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(rsv->svl != S_PHYSICAL_DROP)
5171807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return E_SUB_VECTOR_LENGTH_ERROR;
51721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_issue_write_byte_cmd(dev, RW_PHYSICAL_DROP_NUMBER, &rsv->svv[0]);
51741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_cmd(dev)))
5175807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
51761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5177807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return POSITIVE_ACK;
51781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
51791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Reset the ring speed to the opposite of what it was. This auto-pilot
51811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mode requires a complete reset and re-init of the adapter.
51821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
51831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_ring_speed(struct net_device *dev)
51841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
51851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
51861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
51871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->media_type == MEDIA_UTP_16)
51891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->media_type = MEDIA_UTP_4;
51901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
51911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->media_type = MEDIA_UTP_16;
51921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_enable_16bit(dev);
51941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* Re-Initialize adapter's internal registers */
51961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_reset_adapter(dev);
51971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
51981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_init_card_real(dev)))
5199807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
52001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_enable_bic_int(dev);
52021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_issue_enable_int_cmd(dev, TRC_INTERRUPT_ENABLE_MASK)))
5204807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
52051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        smctr_disable_16bit(dev);
52071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5208807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet	return 0;
52091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
52101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_rx_look_ahead(struct net_device *dev)
52121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
52131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
52141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 sword, rword;
52151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
52171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_set_rx_look_ahead_flag\n", dev->name);
52181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->adapter_flags &= ~(FORCED_16BIT_MODE);
52201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->adapter_flags |= RX_VALID_LOOKAHEAD;
52211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->adapter_bus == BUS_ISA16_TYPE)
52231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
52241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                sword = *((__u16 *)(tp->ram_access));
52251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *((__u16 *)(tp->ram_access)) = 0x1234;
52261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_disable_16bit(dev);
52281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                rword = *((__u16 *)(tp->ram_access));
52291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_enable_16bit(dev);
52301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(rword != 0x1234)
52321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->adapter_flags |= FORCED_16BIT_MODE;
52331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                *((__u16 *)(tp->ram_access)) = sword;
52351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
52361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5237807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
52381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
52391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_set_trc_reset(int ioaddr)
52411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
52421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 r;
52431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        r = inb(ioaddr + MSR);
52451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        outb(MSR_RST | r, ioaddr + MSR);
52461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5247807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
52481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
52491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
52511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function can be called if the adapter is busy or not.
52521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
52531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_setup_single_cmd(struct net_device *dev,
52541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 command, __u16 subcommand)
52551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
52561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
52571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int err;
52581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
52601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_setup_single_cmd\n", dev->name);
52611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = smctr_wait_while_cbusy(dev)))
5263807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
52641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((err = (unsigned int)smctr_wait_cmd(dev)))
5266807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return err;
52671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->acb_head->cmd_done_status   = 0;
52691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->acb_head->cmd               = command;
52701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->acb_head->subcmd            = subcommand;
52711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        err = smctr_issue_resume_acb_cmd(dev);
52731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5274807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
52751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
52761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
52781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function can not be called with the adapter busy.
52791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
52801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_setup_single_cmd_w_data(struct net_device *dev,
52811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 command, __u16 subcommand)
52821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
52831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
52841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->acb_head->cmd_done_status   = ACB_COMMAND_NOT_DONE;
52861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->acb_head->cmd               = command;
52871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->acb_head->subcmd            = subcommand;
52881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->acb_head->data_offset_lo
52891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                = (__u16)TRC_POINTER(tp->misc_command_data);
52901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5291807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return smctr_issue_resume_acb_cmd(dev);
52921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
52931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic char *smctr_malloc(struct net_device *dev, __u16 size)
52951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
52961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
52971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        char *m;
52981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        m = (char *)(tp->ram_access + tp->sh_mem_used);
53001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->sh_mem_used += (__u32)size;
53011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5302807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return m;
53031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
53041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_status_chg(struct net_device *dev)
53061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
53071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
53081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
53101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_status_chg\n", dev->name);
53111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        switch(tp->status)
53131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
53141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case OPEN:
53151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
53161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case CLOSED:
53181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
53191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* Interrupt driven open() completion. XXX */
53211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                case INITIALIZED:
53221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->group_address_0 = 0;
53231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->group_address[0] = 0;
53241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->group_address[1] = 0;
53251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->functional_address_0 = 0;
53261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->functional_address[0] = 0;
53271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->functional_address[1] = 0;
53281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        smctr_open_tr(dev);
53291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
53301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                default:
53321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        printk(KERN_INFO "%s: status change unknown %x\n",
53331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                dev->name, tp->status);
53341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
53351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
53361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5337807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
53381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
53391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_trc_send_packet(struct net_device *dev, FCBlock *fcb,
53411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 queue)
53421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
53431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
53441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int err = 0;
53451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
53471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_trc_send_packet\n", dev->name);
53481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fcb->info = FCB_CHAIN_END | FCB_ENABLE_TFS;
53501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->num_tx_fcbs[queue] != 1)
53511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->back_ptr->info = FCB_INTERRUPT_ENABLE | FCB_ENABLE_TFS;
53521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->tx_queue_status[queue] == NOT_TRANSMITING)
53541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
53551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->tx_queue_status[queue] = TRANSMITING;
53561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                err = smctr_issue_resume_tx_fcb_cmd(dev, queue);
53571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
53581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5359807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
53601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
53611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic __u16 smctr_tx_complete(struct net_device *dev, __u16 queue)
53631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
53641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
53651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 status, err = 0;
53661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int cstatus;
53671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
53691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_tx_complete\n", dev->name);
53701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        while((status = tp->tx_fcb_end[queue]->frame_status) != SUCCESS)
53721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
53731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(status & 0x7e00 )
53741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
53751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        err = HARDWARE_FAILED;
53761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
53771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
53781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if((err = smctr_update_tx_chain(dev, tp->tx_fcb_end[queue],
53801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        queue)) != SUCCESS)
53811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
53821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_disable_16bit(dev);
53841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(tp->mode_bits & UMAC)
53861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
53871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if(!(status & (FCB_TX_STATUS_AR1 | FCB_TX_STATUS_AR2)))
53881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                cstatus = NO_SUCH_DESTINATION;
53891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        else
53901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        {
53911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                if(!(status & (FCB_TX_STATUS_CR1 | FCB_TX_STATUS_CR2)))
53921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        cstatus = DEST_OUT_OF_RESOURCES;
53931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                else
53941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                {
53951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        if(status & FCB_TX_STATUS_E)
53961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                cstatus = MAX_COLLISIONS;
53971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                        else
53981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                                cstatus = SUCCESS;
53991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                }
54001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        }
54011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
54021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
54031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        cstatus = SUCCESS;
54041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(queue == BUG_QUEUE)
54061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        err = SUCCESS;
54071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_enable_16bit(dev);
54091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(err != SUCCESS)
54101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
54111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
54121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5413807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return err;
54141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
54151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned short smctr_tx_move_frame(struct net_device *dev,
54171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct sk_buff *skb, __u8 *pbuff, unsigned int bytes)
54181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
54191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
54201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int ram_usable;
54211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u32 flen, len, offset = 0;
54221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 *frag, *page;
54231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
54251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_tx_move_frame\n", dev->name);
54261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        ram_usable = ((unsigned int)tp->ram_usable) << 10;
54281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        frag       = skb->data;
54291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        flen       = skb->len;
54301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        while(flen > 0 && bytes > 0)
54321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
54331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                smctr_set_page(dev, pbuff);
54341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                offset = SMC_PAGE_OFFSET(pbuff);
54361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(offset + flen > ram_usable)
54381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        len = ram_usable - offset;
54391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                else
54401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        len = flen;
54411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(len > bytes)
54431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        len = bytes;
54441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                page = (char *) (offset + tp->ram_access);
54461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                memcpy(page, frag, len);
54471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                flen -=len;
54491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bytes -= len;
54501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                frag += len;
54511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                pbuff += len;
54521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
54531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5454807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
54551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
54561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Update the error statistic counters for this adapter. */
54581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_update_err_stats(struct net_device *dev)
54591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
54601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
54611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct tr_statistics *tstat = &tp->MacStat;
54621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tstat->internal_errors)
54641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tstat->internal_errors
54651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        += *(tp->misc_command_data + 0) & 0x00ff;
54661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tstat->line_errors)
54681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tstat->line_errors += *(tp->misc_command_data + 0) >> 8;
54691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tstat->A_C_errors)
54711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tstat->A_C_errors += *(tp->misc_command_data + 1) & 0x00ff;
54721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tstat->burst_errors)
54741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tstat->burst_errors += *(tp->misc_command_data + 1) >> 8;
54751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tstat->abort_delimiters)
54771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tstat->abort_delimiters += *(tp->misc_command_data + 2) >> 8;
54781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tstat->recv_congest_count)
54801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tstat->recv_congest_count
54811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        += *(tp->misc_command_data + 3) & 0x00ff;
54821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tstat->lost_frames)
54841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tstat->lost_frames
54851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        += *(tp->misc_command_data + 3) >> 8;
54861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tstat->frequency_errors)
54881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tstat->frequency_errors += *(tp->misc_command_data + 4) & 0x00ff;
54891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tstat->frame_copied_errors)
54911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 tstat->frame_copied_errors
54921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        += *(tp->misc_command_data + 4) >> 8;
54931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tstat->token_errors)
54951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tstat->token_errors += *(tp->misc_command_data + 5) >> 8;
54961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5497807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
54981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
54991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_update_rx_chain(struct net_device *dev, __u16 queue)
55011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
55021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
55031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        FCBlock *fcb;
55041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        BDBlock *bdb;
55051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 size, len;
55061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fcb = tp->rx_fcb_curr[queue];
55081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        len = fcb->frame_length;
55091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fcb->frame_status = 0;
55111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fcb->info = FCB_CHAIN_END;
55121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        fcb->back_ptr->info = FCB_WARNING;
55131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_fcb_curr[queue] = tp->rx_fcb_curr[queue]->next_ptr;
55151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* update RX BDBs */
55171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        size = (len >> RX_BDB_SIZE_SHIFT);
55181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(len & RX_DATA_BUFFER_SIZE_MASK)
55191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                size += sizeof(BDBlock);
55201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        size &= (~RX_BDB_SIZE_MASK);
55211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        /* check if wrap around */
55231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        bdb = (BDBlock *)((__u32)(tp->rx_bdb_curr[queue]) + (__u32)(size));
55241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if((__u32)bdb >= (__u32)tp->rx_bdb_end[queue])
55251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
55261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                bdb = (BDBlock *)((__u32)(tp->rx_bdb_head[queue])
55271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        + (__u32)(bdb) - (__u32)(tp->rx_bdb_end[queue]));
55281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
55291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        bdb->back_ptr->info = BDB_CHAIN_END;
55311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_bdb_curr[queue]->back_ptr->info = BDB_NOT_CHAIN_END;
55321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        tp->rx_bdb_curr[queue] = bdb;
55331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5534807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
55351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
55361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_update_tx_chain(struct net_device *dev, FCBlock *fcb,
55381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u16 queue)
55391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
55401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
55411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 20)
55431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "smctr_update_tx_chain\n");
55441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->num_tx_fcbs_used[queue] <= 0)
5546807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return HARDWARE_FAILED;
55471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
55481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
55491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(tp->tx_buff_used[queue] < fcb->memory_alloc)
55501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
55511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->tx_buff_used[queue] = 0;
5552807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                        return HARDWARE_FAILED;
55531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
55541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->tx_buff_used[queue] -= fcb->memory_alloc;
55561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                /* if all transmit buffer are cleared
55581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * need to set the tx_buff_curr[] to tx_buff_head[]
55591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * otherwise, tx buffer will be segregate and cannot
55601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * accommodate and buffer greater than (curr - head) and
55611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 * (end - curr) since we do not allow wrap around allocation.
55621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                 */
55631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(tp->tx_buff_used[queue] == 0)
55641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        tp->tx_buff_curr[queue] = tp->tx_buff_head[queue];
55651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->num_tx_fcbs_used[queue]--;
55671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                fcb->frame_status = 0;
55681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                tp->tx_fcb_end[queue] = fcb->next_ptr;
55691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		netif_wake_queue(dev);
5570807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return 0;
55711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
55721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
55731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_wait_cmd(struct net_device *dev)
55751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
55761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
55771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int loop_count = 0x20000;
55781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(smctr_debug > 10)
55801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                printk(KERN_DEBUG "%s: smctr_wait_cmd\n", dev->name);
55811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        while(loop_count)
55831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
55841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                if(tp->acb_head->cmd_done_status & ACB_COMMAND_DONE)
55851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        break;
55861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(1);
55871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                loop_count--;
55881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
55891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(loop_count == 0)
5591807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return HARDWARE_FAILED;
55921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->acb_head->cmd_done_status & 0xff)
5594807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return HARDWARE_FAILED;
55951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5596807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet        return 0;
55971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
55981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
55991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int smctr_wait_while_cbusy(struct net_device *dev)
56001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
56011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        struct net_local *tp = netdev_priv(dev);
56021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        unsigned int timeout = 0x20000;
56031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int ioaddr = dev->base_addr;
56041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        __u8 r;
56051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(tp->bic_type == BIC_585_CHIP)
56071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
56081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                while(timeout)
56091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
56101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        r = inb(ioaddr + HWR);
56111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if((r & HWR_CBUSY) == 0)
56121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
56131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        timeout--;
56141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
56151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
56161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
56171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        {
56181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                while(timeout)
56191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                {
56201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        r = inb(ioaddr + CSR);
56211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        if((r & CSR_CBUSY) == 0)
56221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                                break;
56231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                        timeout--;
56241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds                }
56251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
56261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        if(timeout)
5628807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return 0;
56291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        else
5630807540baae406c84dcb9c1c8ef07a56d2d2ae84aEric Dumazet                return HARDWARE_FAILED;
56311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
56321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef MODULE
56341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct net_device* dev_smctr[SMCTR_MAX_ADAPTERS];
56361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int io[SMCTR_MAX_ADAPTERS];
56371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int irq[SMCTR_MAX_ADAPTERS];
56381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
56400f805b86c9492c294c710de8539a8be68b521a86David WoodhouseMODULE_FIRMWARE("tr_smctr.bin");
56411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(io, int, NULL, 0);
56431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param_array(irq, int, NULL, 0);
56441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(ringspeed, int, 0);
56451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5646daca7cd7612639848c39744e02dab537755b31a1Andrew Mortonstatic struct net_device * __init setup_card(int n)
56471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
56481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *dev = alloc_trdev(sizeof(struct net_local));
56491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int err;
56501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dev)
56521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return ERR_PTR(-ENOMEM);
56531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev->irq = irq[n];
56551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = smctr_probe1(dev, io[n]);
56561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
56571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out;
56581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	err = register_netdev(dev);
56601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (err)
56611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto out1;
56621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return dev;
56631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds out1:
56641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_MCA_LEGACY
56651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{ struct net_local *tp = netdev_priv(dev);
56661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	  if (tp->slot_num)
56671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		mca_mark_as_unused(tp->slot_num);
56681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
56691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
56701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	release_region(dev->base_addr, SMCTR_IO_EXTENT);
56711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_irq(dev->irq, dev);
56721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout:
56731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	free_netdev(dev);
56741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ERR_PTR(err);
56751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
56761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5677daca7cd7612639848c39744e02dab537755b31a1Andrew Mortonint __init init_module(void)
56781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
56791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int i, found = 0;
56801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct net_device *dev;
56811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < SMCTR_MAX_ADAPTERS; i++) {
56831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dev = io[0]? setup_card(i) : smctr_probe(-1);
56841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!IS_ERR(dev)) {
56851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			++found;
56861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_smctr[i] = dev;
56871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
56881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
56891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        return found ? 0 : -ENODEV;
56911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
56921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5693afc8eb46c0ea2cab8bc28713b2e0614f015a7516Al Virovoid __exit cleanup_module(void)
56941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
56951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        int i;
56961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
56971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        for(i = 0; i < SMCTR_MAX_ADAPTERS; i++) {
56981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		struct net_device *dev = dev_smctr[i];
56991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
57001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (dev) {
57011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
57021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			unregister_netdev(dev);
57031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_MCA_LEGACY
57041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			{ struct net_local *tp = netdev_priv(dev);
57051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (tp->slot_num)
57061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				mca_mark_as_unused(tp->slot_num);
57071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
57081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
57091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			release_region(dev->base_addr, SMCTR_IO_EXTENT);
57101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (dev->irq)
57111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				free_irq(dev->irq, dev);
57121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
57131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			free_netdev(dev);
57141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
57151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        }
57161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
57171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif /* MODULE */
5718