Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    1) /*======================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    2) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    3)     Device driver for Intel 82365 and compatible PC Card controllers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    4) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    5)     i82365.c 1.265 1999/11/10 18:36:21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    7)     The contents of this file are subject to the Mozilla Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    8)     License Version 1.1 (the "License"); you may not use this file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300    9)     except in compliance with the License. You may obtain a copy of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   10)     the License at http://www.mozilla.org/MPL/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   12)     Software distributed under the License is distributed on an "AS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   13)     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   14)     implied. See the License for the specific language governing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   15)     rights and limitations under the License.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   17)     The initial developer of the original code is David A. Hinds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   18)     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   19)     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   21)     Alternatively, the contents of this file may be used under the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   22)     terms of the GNU General Public License version 2 (the "GPL"), in which
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   23)     case the provisions of the GPL are applicable instead of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   24)     above.  If you wish to allow the use of your version of this file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   25)     only under the terms of the GPL and not to allow others to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   26)     your version of this file under the MPL, indicate your decision
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   27)     by deleting the provisions above and replace them with the notice
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   28)     and other provisions required by the GPL.  If you do not delete
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   29)     the provisions above, a recipient may use your version of this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   30)     file under either the MPL or the GPL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   31)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   32) ======================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   34) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   35) #include <linux/moduleparam.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   36) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   37) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   38) #include <linux/fcntl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   39) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   40) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   41) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   42) #include <linux/timer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   43) #include <linux/ioport.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   44) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   45) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   46) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   47) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   48) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   49) #include <asm/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   50) #include <asm/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   52) #include <pcmcia/ss.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   54) #include <linux/isapnp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   55) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   56) /* ISA-bus controllers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   57) #include "i82365.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   58) #include "cirrus.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   59) #include "vg468.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   60) #include "ricoh.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   63) static irqreturn_t i365_count_irq(int, void *);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   64) static inline int _check_irq(int irq, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   66)     if (request_irq(irq, i365_count_irq, flags, "x", i365_count_irq) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   67) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   68)     free_irq(irq, i365_count_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   69)     return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   72) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   74) /* Parameters that can be set with 'insmod' */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   76) /* Default base address for i82365sl and other ISA chips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   77) static unsigned long i365_base = 0x3e0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   78) /* Should we probe at 0x3e2 for an extra ISA controller? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   79) static int extra_sockets = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   80) /* Specify a socket number to ignore */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   81) static int ignore = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   82) /* Bit map or list of interrupts to choose from */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   83) static u_int irq_mask = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   84) static int irq_list[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   85) static unsigned int irq_list_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   86) /* The card status change interrupt -- 0 means autoselect */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   87) static int cs_irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   88) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   89) /* Probe for safe interrupts? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   90) static int do_scan = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   91) /* Poll status interval -- 0 means default to interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   92) static int poll_interval = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   93) /* External clock time, in nanoseconds.  120 ns = 8.33 MHz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   94) static int cycle_time = 120;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   95) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   96) /* Cirrus options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   97) static int has_dma = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   98) static int has_led = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   99) static int has_ring = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  100) static int dynamic_mode = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  101) static int freq_bypass = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  102) static int setup_time = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  103) static int cmd_time = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  104) static int recov_time = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  106) /* Vadem options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  107) static int async_clock = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  108) static int cable_mode = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  109) static int wakeup = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  111) module_param_hw(i365_base, ulong, ioport, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  112) module_param(ignore, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  113) module_param(extra_sockets, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  114) module_param_hw(irq_mask, int, other, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  115) module_param_hw_array(irq_list, int, irq, &irq_list_count, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  116) module_param_hw(cs_irq, int, irq, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  117) module_param(async_clock, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  118) module_param(cable_mode, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  119) module_param(wakeup, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  120) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  121) module_param(do_scan, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  122) module_param(poll_interval, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  123) module_param(cycle_time, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  124) module_param(has_dma, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  125) module_param(has_led, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  126) module_param(has_ring, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  127) module_param(dynamic_mode, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  128) module_param(freq_bypass, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  129) module_param(setup_time, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  130) module_param(cmd_time, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  131) module_param(recov_time, int, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  133) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  135) struct cirrus_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  136)     u_char		misc1, misc2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  137)     u_char		timer[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  140) struct vg46x_state {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  141)     u_char		ctl, ema;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  142) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  143) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  144) struct i82365_socket {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  145)     u_short		type, flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  146)     struct pcmcia_socket	socket;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  147)     unsigned int	number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  148)     unsigned int	ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  149)     u_short		psock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  150)     u_char		cs_irq, intr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  151)     union {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  152) 	struct cirrus_state		cirrus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  153) 	struct vg46x_state		vg46x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  154)     } state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  155) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  157) /* Where we keep track of our sockets... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  158) static int sockets = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  159) static struct i82365_socket socket[8] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  160)     { 0, }, /* ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  162) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  163) /* Default ISA interrupt mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  164) #define I365_MASK	0xdeb8	/* irq 15,14,12,11,10,9,7,5,4,3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  166) static int grab_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  167) static DEFINE_SPINLOCK(isa_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  168) #define ISA_LOCK(n, f) spin_lock_irqsave(&isa_lock, f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  169) #define ISA_UNLOCK(n, f) spin_unlock_irqrestore(&isa_lock, f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  171) static struct timer_list poll_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  173) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  175) /* These definitions must match the pcic table! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  176) enum pcic_id {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  177)     IS_I82365A, IS_I82365B, IS_I82365DF,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  178)     IS_IBM, IS_RF5Cx96, IS_VLSI, IS_VG468, IS_VG469,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  179)     IS_PD6710, IS_PD672X, IS_VT83C469,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  180) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  182) /* Flags for classifying groups of controllers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  183) #define IS_VADEM	0x0001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  184) #define IS_CIRRUS	0x0002
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  185) #define IS_VIA		0x0010
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  186) #define IS_UNKNOWN	0x0400
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  187) #define IS_VG_PWR	0x0800
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  188) #define IS_DF_PWR	0x1000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  189) #define IS_REGISTERED	0x2000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  190) #define IS_ALIVE	0x8000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  192) struct pcic {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  193)     char		*name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  194)     u_short		flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  195) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  197) static struct pcic pcic[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  198)     { "Intel i82365sl A step", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  199)     { "Intel i82365sl B step", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  200)     { "Intel i82365sl DF", IS_DF_PWR },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  201)     { "IBM Clone", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  202)     { "Ricoh RF5C296/396", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  203)     { "VLSI 82C146", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  204)     { "Vadem VG-468", IS_VADEM },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  205)     { "Vadem VG-469", IS_VADEM|IS_VG_PWR },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  206)     { "Cirrus PD6710", IS_CIRRUS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  207)     { "Cirrus PD672x", IS_CIRRUS },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  208)     { "VIA VT83C469", IS_CIRRUS|IS_VIA },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  209) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  211) #define PCIC_COUNT	ARRAY_SIZE(pcic)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  212) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  213) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  215) static DEFINE_SPINLOCK(bus_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  216) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  217) static u_char i365_get(u_short sock, u_short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  219)     unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  220)     spin_lock_irqsave(&bus_lock,flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  221)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  222) 	unsigned int port = socket[sock].ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  223) 	u_char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  224) 	reg = I365_REG(socket[sock].psock, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  225) 	outb(reg, port); val = inb(port+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  226) 	spin_unlock_irqrestore(&bus_lock,flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  227) 	return val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  228)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  231) static void i365_set(u_short sock, u_short reg, u_char data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  232) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  233)     unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  234)     spin_lock_irqsave(&bus_lock,flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  235)     {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  236) 	unsigned int port = socket[sock].ioaddr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  237) 	u_char val = I365_REG(socket[sock].psock, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  238) 	outb(val, port); outb(data, port+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  239) 	spin_unlock_irqrestore(&bus_lock,flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  240)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  242) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  243) static void i365_bset(u_short sock, u_short reg, u_char mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  245)     u_char d = i365_get(sock, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  246)     d |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  247)     i365_set(sock, reg, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  250) static void i365_bclr(u_short sock, u_short reg, u_char mask)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  251) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  252)     u_char d = i365_get(sock, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  253)     d &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  254)     i365_set(sock, reg, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  257) static void i365_bflip(u_short sock, u_short reg, u_char mask, int b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  259)     u_char d = i365_get(sock, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  260)     if (b)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  261) 	d |= mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  262)     else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  263) 	d &= ~mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  264)     i365_set(sock, reg, d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  266) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  267) static u_short i365_get_pair(u_short sock, u_short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  268) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  269)     u_short a, b;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  270)     a = i365_get(sock, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  271)     b = i365_get(sock, reg+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  272)     return (a + (b<<8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  275) static void i365_set_pair(u_short sock, u_short reg, u_short data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  277)     i365_set(sock, reg, data & 0xff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  278)     i365_set(sock, reg+1, data >> 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  280) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  281) /*======================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  283)     Code to save and restore global state information for Cirrus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  284)     PD67xx controllers, and to set and report global configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  285)     options.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  287)     The VIA controllers also use these routines, as they are mostly
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  288)     Cirrus lookalikes, without the timing registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  289)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  290) ======================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  291) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  292) #define flip(v,b,f) (v = ((f)<0) ? v : ((f) ? ((v)|(b)) : ((v)&(~b))))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  294) static void cirrus_get_state(u_short s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  295) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  296)     int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  297)     struct cirrus_state *p = &socket[s].state.cirrus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  298)     p->misc1 = i365_get(s, PD67_MISC_CTL_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  299)     p->misc1 &= (PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  300)     p->misc2 = i365_get(s, PD67_MISC_CTL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  301)     for (i = 0; i < 6; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  302) 	p->timer[i] = i365_get(s, PD67_TIME_SETUP(0)+i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  305) static void cirrus_set_state(u_short s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  306) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  307)     int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  308)     u_char misc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  309)     struct cirrus_state *p = &socket[s].state.cirrus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  310) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  311)     misc = i365_get(s, PD67_MISC_CTL_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  312)     i365_set(s, PD67_MISC_CTL_2, p->misc2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  313)     if (misc & PD67_MC2_SUSPEND) mdelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  314)     misc = i365_get(s, PD67_MISC_CTL_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  315)     misc &= ~(PD67_MC1_MEDIA_ENA | PD67_MC1_INPACK_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  316)     i365_set(s, PD67_MISC_CTL_1, misc | p->misc1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  317)     for (i = 0; i < 6; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  318) 	i365_set(s, PD67_TIME_SETUP(0)+i, p->timer[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  321) static u_int __init cirrus_set_opts(u_short s, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  323)     struct i82365_socket *t = &socket[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  324)     struct cirrus_state *p = &socket[s].state.cirrus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  325)     u_int mask = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  327)     if (has_ring == -1) has_ring = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  328)     flip(p->misc2, PD67_MC2_IRQ15_RI, has_ring);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  329)     flip(p->misc2, PD67_MC2_DYNAMIC_MODE, dynamic_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  330)     flip(p->misc2, PD67_MC2_FREQ_BYPASS, freq_bypass);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  331)     if (p->misc2 & PD67_MC2_IRQ15_RI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  332) 	strcat(buf, " [ring]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  333)     if (p->misc2 & PD67_MC2_DYNAMIC_MODE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  334) 	strcat(buf, " [dyn mode]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  335)     if (p->misc2 & PD67_MC2_FREQ_BYPASS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  336) 	strcat(buf, " [freq bypass]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  337)     if (p->misc1 & PD67_MC1_INPACK_ENA)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  338) 	strcat(buf, " [inpack]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  339)     if (p->misc2 & PD67_MC2_IRQ15_RI)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  340) 	mask &= ~0x8000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  341)     if (has_led > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  342) 	strcat(buf, " [led]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  343) 	mask &= ~0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  344)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  345)     if (has_dma > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  346) 	strcat(buf, " [dma]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  347) 	mask &= ~0x0600;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  348)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  349)     if (!(t->flags & IS_VIA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  350) 	if (setup_time >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  351) 	    p->timer[0] = p->timer[3] = setup_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  352) 	if (cmd_time > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  353) 	    p->timer[1] = cmd_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  354) 	    p->timer[4] = cmd_time*2+4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  355) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  356) 	if (p->timer[1] == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  357) 	    p->timer[1] = 6; p->timer[4] = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  358) 	    if (p->timer[0] == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  359) 		p->timer[0] = p->timer[3] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  360) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  361) 	if (recov_time >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  362) 	    p->timer[2] = p->timer[5] = recov_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  363) 	buf += strlen(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  364) 	sprintf(buf, " [%d/%d/%d] [%d/%d/%d]", p->timer[0], p->timer[1],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  365) 		p->timer[2], p->timer[3], p->timer[4], p->timer[5]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  366)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  367)     return mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  369) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  370) /*======================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  372)     Code to save and restore global state information for Vadem VG468
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  373)     and VG469 controllers, and to set and report global configuration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  374)     options.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  375)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  376) ======================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  378) static void vg46x_get_state(u_short s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  380)     struct vg46x_state *p = &socket[s].state.vg46x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  381)     p->ctl = i365_get(s, VG468_CTL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  382)     if (socket[s].type == IS_VG469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  383) 	p->ema = i365_get(s, VG469_EXT_MODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  384) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  386) static void vg46x_set_state(u_short s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  387) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  388)     struct vg46x_state *p = &socket[s].state.vg46x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  389)     i365_set(s, VG468_CTL, p->ctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  390)     if (socket[s].type == IS_VG469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  391) 	i365_set(s, VG469_EXT_MODE, p->ema);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  392) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  394) static u_int __init vg46x_set_opts(u_short s, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  395) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  396)     struct vg46x_state *p = &socket[s].state.vg46x;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  397)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  398)     flip(p->ctl, VG468_CTL_ASYNC, async_clock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  399)     flip(p->ema, VG469_MODE_CABLE, cable_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  400)     if (p->ctl & VG468_CTL_ASYNC)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  401) 	strcat(buf, " [async]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  402)     if (p->ctl & VG468_CTL_INPACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  403) 	strcat(buf, " [inpack]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  404)     if (socket[s].type == IS_VG469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  405) 	u_char vsel = i365_get(s, VG469_VSELECT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  406) 	if (vsel & VG469_VSEL_EXT_STAT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  407) 	    strcat(buf, " [ext mode]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  408) 	    if (vsel & VG469_VSEL_EXT_BUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  409) 		strcat(buf, " [isa buf]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  410) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  411) 	if (p->ema & VG469_MODE_CABLE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  412) 	    strcat(buf, " [cable]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  413) 	if (p->ema & VG469_MODE_COMPAT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  414) 	    strcat(buf, " [c step]");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  415)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  416)     return 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  418) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  419) /*======================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  420) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  421)     Generic routines to get and set controller options
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  422)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  423) ======================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  424) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  425) static void get_bridge_state(u_short s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  427)     struct i82365_socket *t = &socket[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  428)     if (t->flags & IS_CIRRUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  429) 	cirrus_get_state(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  430)     else if (t->flags & IS_VADEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  431) 	vg46x_get_state(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  432) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  433) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  434) static void set_bridge_state(u_short s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  435) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  436)     struct i82365_socket *t = &socket[s];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  437)     if (t->flags & IS_CIRRUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  438) 	cirrus_set_state(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  439)     else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  440) 	i365_set(s, I365_GBLCTL, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  441) 	i365_set(s, I365_GENCTL, 0x00);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  442)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  443)     i365_bflip(s, I365_INTCTL, I365_INTR_ENA, t->intr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  444)     if (t->flags & IS_VADEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  445) 	vg46x_set_state(s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  447) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  448) static u_int __init set_bridge_opts(u_short s, u_short ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  449) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  450)     u_short i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  451)     u_int m = 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  452)     char buf[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  454)     for (i = s; i < s+ns; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  455) 	if (socket[i].flags & IS_ALIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  456) 	    printk(KERN_INFO "    host opts [%d]: already alive!\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  457) 	    continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  458) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  459) 	buf[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  460) 	get_bridge_state(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  461) 	if (socket[i].flags & IS_CIRRUS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  462) 	    m = cirrus_set_opts(i, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  463) 	else if (socket[i].flags & IS_VADEM)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  464) 	    m = vg46x_set_opts(i, buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  465) 	set_bridge_state(i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  466) 	printk(KERN_INFO "    host opts [%d]:%s\n", i,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  467) 	       (*buf) ? buf : " none");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  468)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  469)     return m;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  471) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  472) /*======================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  473) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  474)     Interrupt testing code, for ISA and PCI interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  475)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  476) ======================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  477) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  478) static volatile u_int irq_hits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  479) static u_short irq_sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  480) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  481) static irqreturn_t i365_count_irq(int irq, void *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  482) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  483)     i365_get(irq_sock, I365_CSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  484)     irq_hits++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  485)     pr_debug("i82365: -> hit on irq %d\n", irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  486)     return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  488) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  489) static u_int __init test_irq(u_short sock, int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  490) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  491)     pr_debug("i82365:  testing ISA irq %d\n", irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  492)     if (request_irq(irq, i365_count_irq, IRQF_PROBE_SHARED, "scan",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  493) 			i365_count_irq) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  494) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  495)     irq_hits = 0; irq_sock = sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  496)     msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  497)     if (irq_hits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  498) 	free_irq(irq, i365_count_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  499) 	pr_debug("i82365:    spurious hit!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  500) 	return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  501)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  502) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  503)     /* Generate one interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  504)     i365_set(sock, I365_CSCINT, I365_CSC_DETECT | (irq << 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  505)     i365_bset(sock, I365_GENCTL, I365_CTL_SW_IRQ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  506)     udelay(1000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  508)     free_irq(irq, i365_count_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  509) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  510)     /* mask all interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  511)     i365_set(sock, I365_CSCINT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  512)     pr_debug("i82365:    hits = %d\n", irq_hits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  513)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  514)     return (irq_hits != 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  515) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  516) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  517) static u_int __init isa_scan(u_short sock, u_int mask0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  518) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  519)     u_int mask1 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  520)     int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  521) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  522) #ifdef __alpha__
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  523) #define PIC 0x4d0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  524)     /* Don't probe level-triggered interrupts -- reserved for PCI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  525)     mask0 &= ~(inb(PIC) | (inb(PIC+1) << 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  526) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  527)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  528)     if (do_scan) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  529) 	set_bridge_state(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  530) 	i365_set(sock, I365_CSCINT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  531) 	for (i = 0; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  532) 	    if ((mask0 & (1 << i)) && (test_irq(sock, i) == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  533) 		mask1 |= (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  534) 	for (i = 0; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  535) 	    if ((mask1 & (1 << i)) && (test_irq(sock, i) != 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  536) 		mask1 ^= (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  537)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  538)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  539)     printk(KERN_INFO "    ISA irqs (");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  540)     if (mask1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  541) 	printk("scanned");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  542)     } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  543) 	/* Fallback: just find interrupts that aren't in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  544) 	for (i = 0; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  545) 	    if ((mask0 & (1 << i)) && (_check_irq(i, IRQF_PROBE_SHARED) == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  546) 		mask1 |= (1 << i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  547) 	printk("default");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  548) 	/* If scan failed, default to polled status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  549) 	if (!cs_irq && (poll_interval == 0)) poll_interval = HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  550)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  551)     printk(") = ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  552)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  553)     for (i = 0; i < 16; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  554) 	if (mask1 & (1<<i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  555) 	    printk("%s%d", ((mask1 & ((1<<i)-1)) ? "," : ""), i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  556)     if (mask1 == 0) printk("none!");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  557)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  558)     return mask1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  559) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  560) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  561) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  562) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  563) /* Time conversion functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  564) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  565) static int to_cycles(int ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  566) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  567)     return ns/cycle_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  568) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  569) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  570) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  571) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  572) static int __init identify(unsigned int port, u_short sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  573) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  574)     u_char val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  575)     int type = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  576) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  577)     /* Use the next free entry in the socket table */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  578)     socket[sockets].ioaddr = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  579)     socket[sockets].psock = sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  580)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  581)     /* Wake up a sleepy Cirrus controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  582)     if (wakeup) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  583) 	i365_bclr(sockets, PD67_MISC_CTL_2, PD67_MC2_SUSPEND);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  584) 	/* Pause at least 50 ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  585) 	mdelay(50);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  586)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  587)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  588)     if ((val = i365_get(sockets, I365_IDENT)) & 0x70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  589) 	return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  590)     switch (val) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  591)     case 0x82:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  592) 	type = IS_I82365A; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  593)     case 0x83:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  594) 	type = IS_I82365B; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  595)     case 0x84:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  596) 	type = IS_I82365DF; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  597)     case 0x88: case 0x89: case 0x8a:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  598) 	type = IS_IBM; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  599)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  600)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  601)     /* Check for Vadem VG-468 chips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  602)     outb(0x0e, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  603)     outb(0x37, port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  604)     i365_bset(sockets, VG468_MISC, VG468_MISC_VADEMREV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  605)     val = i365_get(sockets, I365_IDENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  606)     if (val & I365_IDENT_VADEM) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  607) 	i365_bclr(sockets, VG468_MISC, VG468_MISC_VADEMREV);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  608) 	type = ((val & 7) >= 4) ? IS_VG469 : IS_VG468;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  609)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  610) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  611)     /* Check for Ricoh chips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  612)     val = i365_get(sockets, RF5C_CHIP_ID);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  613)     if ((val == RF5C_CHIP_RF5C296) || (val == RF5C_CHIP_RF5C396))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  614) 	type = IS_RF5Cx96;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  615)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  616)     /* Check for Cirrus CL-PD67xx chips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  617)     i365_set(sockets, PD67_CHIP_INFO, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  618)     val = i365_get(sockets, PD67_CHIP_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  619)     if ((val & PD67_INFO_CHIP_ID) == PD67_INFO_CHIP_ID) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  620) 	val = i365_get(sockets, PD67_CHIP_INFO);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  621) 	if ((val & PD67_INFO_CHIP_ID) == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  622) 	    type = (val & PD67_INFO_SLOTS) ? IS_PD672X : IS_PD6710;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  623) 	    i365_set(sockets, PD67_EXT_INDEX, 0xe5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  624) 	    if (i365_get(sockets, PD67_EXT_INDEX) != 0xe5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  625) 		type = IS_VT83C469;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  626) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  627)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  628)     return type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  629) } /* identify */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  630) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  631) /*======================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  632) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  633)     See if a card is present, powered up, in IO mode, and already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  634)     bound to a (non PC Card) Linux driver.  We leave these alone.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  635) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  636)     We make an exception for cards that seem to be serial devices.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  637)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  638) ======================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  639) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  640) static int __init is_alive(u_short sock)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  642)     u_char stat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  643)     unsigned int start, stop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  644)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  645)     stat = i365_get(sock, I365_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  646)     start = i365_get_pair(sock, I365_IO(0)+I365_W_START);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  647)     stop = i365_get_pair(sock, I365_IO(0)+I365_W_STOP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  648)     if ((stat & I365_CS_DETECT) && (stat & I365_CS_POWERON) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  649) 	(i365_get(sock, I365_INTCTL) & I365_PC_IOCARD) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  650) 	(i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(0)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  651) 	((start & 0xfeef) != 0x02e8)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  652) 	if (!request_region(start, stop-start+1, "i82365"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  653) 	    return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  654) 	release_region(start, stop-start+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  655)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  656) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  657)     return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  658) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  659) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  660) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  661) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  662) static void __init add_socket(unsigned int port, int psock, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  664)     socket[sockets].ioaddr = port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  665)     socket[sockets].psock = psock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  666)     socket[sockets].type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  667)     socket[sockets].flags = pcic[type].flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  668)     if (is_alive(sockets))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  669) 	socket[sockets].flags |= IS_ALIVE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  670)     sockets++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  671) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  672) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  673) static void __init add_pcic(int ns, int type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  674) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  675)     u_int mask = 0, i, base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  676)     int isa_irq = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  677)     struct i82365_socket *t = &socket[sockets-ns];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  678) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  679)     base = sockets-ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  680)     if (base == 0) printk("\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  681)     printk(KERN_INFO "  %s", pcic[type].name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  682)     printk(" ISA-to-PCMCIA at port %#x ofs 0x%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  683) 	       t->ioaddr, t->psock*0x40);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  684)     printk(", %d socket%s\n", ns, ((ns > 1) ? "s" : ""));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  685) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  686)     /* Set host options, build basic interrupt mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  687)     if (irq_list_count == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  688) 	mask = irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  689)     else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  690) 	for (i = mask = 0; i < irq_list_count; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  691) 	    mask |= (1<<irq_list[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  692)     mask &= I365_MASK & set_bridge_opts(base, ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  693)     /* Scan for ISA interrupts */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  694)     mask = isa_scan(base, mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  695)         
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  696)     /* Poll if only two interrupts available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  697)     if (!poll_interval) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  698) 	u_int tmp = (mask & 0xff20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  699) 	tmp = tmp & (tmp-1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  700) 	if ((tmp & (tmp-1)) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  701) 	    poll_interval = HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  702)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  703)     /* Only try an ISA cs_irq if this is the first controller */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  704)     if (!grab_irq && (cs_irq || !poll_interval)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  705) 	/* Avoid irq 12 unless it is explicitly requested */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  706) 	u_int cs_mask = mask & ((cs_irq) ? (1<<cs_irq) : ~(1<<12));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  707) 	for (cs_irq = 15; cs_irq > 0; cs_irq--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  708) 	    if ((cs_mask & (1 << cs_irq)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  709) 		(_check_irq(cs_irq, IRQF_PROBE_SHARED) == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  710) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  711) 	if (cs_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  712) 	    grab_irq = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  713) 	    isa_irq = cs_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  714) 	    printk(" status change on irq %d\n", cs_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  715) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  716)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  717)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  718)     if (!isa_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  719) 	if (poll_interval == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  720) 	    poll_interval = HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  721) 	printk(" polling interval = %d ms\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  722) 	       poll_interval * 1000 / HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  723) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  724)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  725)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  726)     /* Update socket interrupt information, capabilities */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  727)     for (i = 0; i < ns; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  728) 	t[i].socket.features |= SS_CAP_PCCARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  729) 	t[i].socket.map_size = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  730) 	t[i].socket.irq_mask = mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  731) 	t[i].cs_irq = isa_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  732)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  733) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  734) } /* add_pcic */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  735) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  736) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  737) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  738) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  739) static struct isapnp_device_id id_table[] __initdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  740) 	{ 	ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  741) 		ISAPNP_FUNCTION(0x0e00), (unsigned long) "Intel 82365-Compatible" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  742) 	{ 	ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  743) 		ISAPNP_FUNCTION(0x0e01), (unsigned long) "Cirrus Logic CL-PD6720" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  744) 	{ 	ISAPNP_ANY_ID, ISAPNP_ANY_ID, ISAPNP_VENDOR('P', 'N', 'P'),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  745) 		ISAPNP_FUNCTION(0x0e02), (unsigned long) "VLSI VL82C146" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  746) 	{	0 }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  747) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  748) MODULE_DEVICE_TABLE(isapnp, id_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  749) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  750) static struct pnp_dev *i82365_pnpdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  751) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  752) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  753) static void __init isa_probe(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  754) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  755)     int i, j, sock, k, ns, id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  756)     unsigned int port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  757) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  758)     struct isapnp_device_id *devid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  759)     struct pnp_dev *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  760) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  761)     for (devid = id_table; devid->vendor; devid++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  762) 	if ((dev = pnp_find_dev(NULL, devid->vendor, devid->function, NULL))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  763) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  764) 	    if (pnp_device_attach(dev) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  765) 	    	continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  766) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  767) 	    if (pnp_activate_dev(dev) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  768) 		printk("activate failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  769) 		pnp_device_detach(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  770) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  771) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  772) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  773) 	    if (!pnp_port_valid(dev, 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  774) 		printk("invalid resources ?\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  775) 		pnp_device_detach(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  776) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  777) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  778) 	    i365_base = pnp_port_start(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  779) 	    i82365_pnpdev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  780) 	    break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  781) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  782)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  783) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  784) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  785)     if (!request_region(i365_base, 2, "i82365")) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  786) 	if (sockets == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  787) 	    printk("port conflict at %#lx\n", i365_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  788) 	return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  789)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  790) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  791)     id = identify(i365_base, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  792)     if ((id == IS_I82365DF) && (identify(i365_base, 1) != id)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  793) 	for (i = 0; i < 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  794) 	    if (i == ignore) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  795) 	    port = i365_base + ((i & 1) << 2) + ((i & 2) << 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  796) 	    sock = (i & 1) << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  797) 	    if (identify(port, sock) == IS_I82365DF) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  798) 		add_socket(port, sock, IS_VLSI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  799) 		add_pcic(1, IS_VLSI);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  800) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  801) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  802)     } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  803) 	for (i = 0; i < 8; i += 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  804) 	    if (sockets && !extra_sockets && (i == 4))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  805) 		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  806) 	    port = i365_base + 2*(i>>2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  807) 	    sock = (i & 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  808) 	    id = identify(port, sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  809) 	    if (id < 0) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  810) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  811) 	    for (j = ns = 0; j < 2; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  812) 		/* Does the socket exist? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  813) 		if ((ignore == i+j) || (identify(port, sock+j) < 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  814) 		    continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  815) 		/* Check for bad socket decode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  816) 		for (k = 0; k <= sockets; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  817) 		    i365_set(k, I365_MEM(0)+I365_W_OFF, k);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  818) 		for (k = 0; k <= sockets; k++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  819) 		    if (i365_get(k, I365_MEM(0)+I365_W_OFF) != k)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  820) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  821) 		if (k <= sockets) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  822) 		add_socket(port, sock+j, id); ns++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  823) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  824) 	    if (ns != 0) add_pcic(ns, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  825) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  826)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  828) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  829) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  830) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  831) static irqreturn_t pcic_interrupt(int irq, void *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  832) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  833)     int i, j, csc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  834)     u_int events, active;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  835)     u_long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  836)     int handled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  837) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  838)     pr_debug("pcic_interrupt(%d)\n", irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  839) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  840)     for (j = 0; j < 20; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  841) 	active = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  842) 	for (i = 0; i < sockets; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  843) 	    if (socket[i].cs_irq != irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  844) 		continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  845) 	    handled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  846) 	    ISA_LOCK(i, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  847) 	    csc = i365_get(i, I365_CSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  848) 	    if ((csc == 0) || (i365_get(i, I365_IDENT) & 0x70)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  849) 		ISA_UNLOCK(i, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  850) 		continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  851) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  852) 	    events = (csc & I365_CSC_DETECT) ? SS_DETECT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  853) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  854) 	    if (i365_get(i, I365_INTCTL) & I365_PC_IOCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  855) 		events |= (csc & I365_CSC_STSCHG) ? SS_STSCHG : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  856) 	    else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  857) 		events |= (csc & I365_CSC_BVD1) ? SS_BATDEAD : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  858) 		events |= (csc & I365_CSC_BVD2) ? SS_BATWARN : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  859) 		events |= (csc & I365_CSC_READY) ? SS_READY : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  860) 	    }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  861) 	    ISA_UNLOCK(i, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  862) 	    pr_debug("socket %d event 0x%02x\n", i, events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  863) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  864) 	    if (events)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  865) 		pcmcia_parse_events(&socket[i].socket, events);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  866) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  867) 	    active |= events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  868) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  869) 	if (!active) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  870)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  871)     if (j == 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  872) 	printk(KERN_NOTICE "i82365: infinite loop in interrupt handler\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  873) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  874)     pr_debug("pcic_interrupt done\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  875)     return IRQ_RETVAL(handled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  876) } /* pcic_interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  877) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  878) static void pcic_interrupt_wrapper(struct timer_list *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  879) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  880)     pcic_interrupt(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  881)     poll_timer.expires = jiffies + poll_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  882)     add_timer(&poll_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  884) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  885) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  886) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  887) static int i365_get_status(u_short sock, u_int *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  888) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  889)     u_int status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  890)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  891)     status = i365_get(sock, I365_STATUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  892)     *value = ((status & I365_CS_DETECT) == I365_CS_DETECT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  893) 	? SS_DETECT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  894) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  895)     if (i365_get(sock, I365_INTCTL) & I365_PC_IOCARD)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  896) 	*value |= (status & I365_CS_STSCHG) ? 0 : SS_STSCHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  897)     else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  898) 	*value |= (status & I365_CS_BVD1) ? 0 : SS_BATDEAD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  899) 	*value |= (status & I365_CS_BVD2) ? 0 : SS_BATWARN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  900)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  901)     *value |= (status & I365_CS_WRPROT) ? SS_WRPROT : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  902)     *value |= (status & I365_CS_READY) ? SS_READY : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  903)     *value |= (status & I365_CS_POWERON) ? SS_POWERON : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  904) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  905)     if (socket[sock].type == IS_VG469) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  906) 	status = i365_get(sock, VG469_VSENSE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  907) 	if (socket[sock].psock & 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  908) 	    *value |= (status & VG469_VSENSE_B_VS1) ? 0 : SS_3VCARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  909) 	    *value |= (status & VG469_VSENSE_B_VS2) ? 0 : SS_XVCARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  910) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  911) 	    *value |= (status & VG469_VSENSE_A_VS1) ? 0 : SS_3VCARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  912) 	    *value |= (status & VG469_VSENSE_A_VS2) ? 0 : SS_XVCARD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  913) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  914)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  915)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  916)     pr_debug("GetStatus(%d) = %#4.4x\n", sock, *value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  917)     return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  918) } /* i365_get_status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  919) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  920) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  921) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  922) static int i365_set_socket(u_short sock, socket_state_t *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  923) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  924)     struct i82365_socket *t = &socket[sock];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  925)     u_char reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  926)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  927)     pr_debug("SetSocket(%d, flags %#3.3x, Vcc %d, Vpp %d, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  928) 	  "io_irq %d, csc_mask %#2.2x)\n", sock, state->flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  929) 	  state->Vcc, state->Vpp, state->io_irq, state->csc_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  930)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  931)     /* First set global controller options */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  932)     set_bridge_state(sock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  933)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  934)     /* IO card, RESET flag, IO interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  935)     reg = t->intr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  936)     reg |= state->io_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  937)     reg |= (state->flags & SS_RESET) ? 0 : I365_PC_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  938)     reg |= (state->flags & SS_IOCARD) ? I365_PC_IOCARD : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  939)     i365_set(sock, I365_INTCTL, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  940)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  941)     reg = I365_PWR_NORESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  942)     if (state->flags & SS_PWR_AUTO) reg |= I365_PWR_AUTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  943)     if (state->flags & SS_OUTPUT_ENA) reg |= I365_PWR_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  944) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  945)     if (t->flags & IS_CIRRUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  946) 	if (state->Vpp != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  947) 	    if (state->Vpp == 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  948) 		reg |= I365_VPP1_12V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  949) 	    else if (state->Vpp == state->Vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  950) 		reg |= I365_VPP1_5V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  951) 	    else return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  952) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  953) 	if (state->Vcc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  954) 	    reg |= I365_VCC_5V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  955) 	    if (state->Vcc == 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  956) 		i365_bset(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  957) 	    else if (state->Vcc == 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  958) 		i365_bclr(sock, PD67_MISC_CTL_1, PD67_MC1_VCC_3V);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  959) 	    else return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  960) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  961)     } else if (t->flags & IS_VG_PWR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  962) 	if (state->Vpp != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  963) 	    if (state->Vpp == 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  964) 		reg |= I365_VPP1_12V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  965) 	    else if (state->Vpp == state->Vcc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  966) 		reg |= I365_VPP1_5V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  967) 	    else return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  968) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  969) 	if (state->Vcc != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  970) 	    reg |= I365_VCC_5V;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  971) 	    if (state->Vcc == 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  972) 		i365_bset(sock, VG469_VSELECT, VG469_VSEL_VCC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  973) 	    else if (state->Vcc == 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  974) 		i365_bclr(sock, VG469_VSELECT, VG469_VSEL_VCC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  975) 	    else return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  976) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  977)     } else if (t->flags & IS_DF_PWR) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  978) 	switch (state->Vcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  979) 	case 0:		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  980) 	case 33:   	reg |= I365_VCC_3V; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  981) 	case 50:	reg |= I365_VCC_5V; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  982) 	default:	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  983) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  984) 	switch (state->Vpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  985) 	case 0:		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  986) 	case 50:   	reg |= I365_VPP1_5V; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  987) 	case 120:	reg |= I365_VPP1_12V; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  988) 	default:	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  989) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  990)     } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  991) 	switch (state->Vcc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  992) 	case 0:		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  993) 	case 50:	reg |= I365_VCC_5V; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  994) 	default:	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  995) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  996) 	switch (state->Vpp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  997) 	case 0:		break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  998) 	case 50:	reg |= I365_VPP1_5V | I365_VPP2_5V; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  999) 	case 120:	reg |= I365_VPP1_12V | I365_VPP2_12V; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) 	default:	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004)     if (reg != i365_get(sock, I365_POWER))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) 	i365_set(sock, I365_POWER, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)     /* Chipset-specific functions */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)     if (t->flags & IS_CIRRUS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) 	/* Speaker control */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) 	i365_bflip(sock, PD67_MISC_CTL_1, PD67_MC1_SPKR_ENA,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) 		   state->flags & SS_SPKR_ENA);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)     /* Card status change interrupt mask */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)     reg = t->cs_irq << 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016)     if (state->csc_mask & SS_DETECT) reg |= I365_CSC_DETECT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)     if (state->flags & SS_IOCARD) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) 	if (state->csc_mask & SS_STSCHG) reg |= I365_CSC_STSCHG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)     } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) 	if (state->csc_mask & SS_BATDEAD) reg |= I365_CSC_BVD1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) 	if (state->csc_mask & SS_BATWARN) reg |= I365_CSC_BVD2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) 	if (state->csc_mask & SS_READY) reg |= I365_CSC_READY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)     i365_set(sock, I365_CSCINT, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)     i365_get(sock, I365_CSC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027)     return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) } /* i365_set_socket */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034)     u_char map, ioctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)     pr_debug("SetIOMap(%d, %d, %#2.2x, %d ns, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) 	  "%#llx-%#llx)\n", sock, io->map, io->flags, io->speed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) 	  (unsigned long long)io->start, (unsigned long long)io->stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039)     map = io->map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)     if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) 	(io->stop < io->start)) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)     /* Turn off the window before changing anything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)     if (i365_get(sock, I365_ADDRWIN) & I365_ENA_IO(map))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) 	i365_bclr(sock, I365_ADDRWIN, I365_ENA_IO(map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)     i365_set_pair(sock, I365_IO(map)+I365_W_START, io->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)     i365_set_pair(sock, I365_IO(map)+I365_W_STOP, io->stop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047)     ioctl = i365_get(sock, I365_IOCTL) & ~I365_IOCTL_MASK(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048)     if (io->speed) ioctl |= I365_IOCTL_WAIT(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)     if (io->flags & MAP_0WS) ioctl |= I365_IOCTL_0WS(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)     if (io->flags & MAP_16BIT) ioctl |= I365_IOCTL_16BIT(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051)     if (io->flags & MAP_AUTOSZ) ioctl |= I365_IOCTL_IOCS16(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)     i365_set(sock, I365_IOCTL, ioctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)     /* Turn on the window if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)     if (io->flags & MAP_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) 	i365_bset(sock, I365_ADDRWIN, I365_ENA_IO(map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)     return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) } /* i365_set_io_map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) static int i365_set_mem_map(u_short sock, struct pccard_mem_map *mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063)     u_short base, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)     u_char map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066)     pr_debug("SetMemMap(%d, %d, %#2.2x, %d ns, %#llx-%#llx, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) 	  "%#x)\n", sock, mem->map, mem->flags, mem->speed,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) 	  (unsigned long long)mem->res->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) 	  (unsigned long long)mem->res->end, mem->card_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)     map = mem->map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)     if ((map > 4) || (mem->card_start > 0x3ffffff) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) 	(mem->res->start > mem->res->end) || (mem->speed > 1000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075)     if ((mem->res->start > 0xffffff) || (mem->res->end > 0xffffff))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) 	return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)     /* Turn off the window before changing anything */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)     if (i365_get(sock, I365_ADDRWIN) & I365_ENA_MEM(map))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) 	i365_bclr(sock, I365_ADDRWIN, I365_ENA_MEM(map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082)     base = I365_MEM(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)     i = (mem->res->start >> 12) & 0x0fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)     if (mem->flags & MAP_16BIT) i |= I365_MEM_16BIT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085)     if (mem->flags & MAP_0WS) i |= I365_MEM_0WS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086)     i365_set_pair(sock, base+I365_W_START, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)     i = (mem->res->end >> 12) & 0x0fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)     switch (to_cycles(mem->speed)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090)     case 0:	break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)     case 1:	i |= I365_MEM_WS0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)     case 2:	i |= I365_MEM_WS1; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093)     default:	i |= I365_MEM_WS1 | I365_MEM_WS0; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095)     i365_set_pair(sock, base+I365_W_STOP, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)     i = ((mem->card_start - mem->res->start) >> 12) & 0x3fff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)     if (mem->flags & MAP_WRPROT) i |= I365_MEM_WRPROT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)     if (mem->flags & MAP_ATTRIB) i |= I365_MEM_REG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100)     i365_set_pair(sock, base+I365_W_OFF, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)     /* Turn on the window if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)     if (mem->flags & MAP_ACTIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) 	i365_bset(sock, I365_ADDRWIN, I365_ENA_MEM(map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)     return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) } /* i365_set_mem_map */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) #if 0 /* driver model ordering issue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) /*======================================================================
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)     Routines for accessing socket information and register dumps via
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)     /sys/class/pcmcia_socket/...
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) ======================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) static ssize_t show_info(struct class_device *class_dev, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) 	struct i82365_socket *s = container_of(class_dev, struct i82365_socket, socket.dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) 	return sprintf(buf, "type:     %s\npsock:    %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) 		       pcic[s->type].name, s->psock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) static ssize_t show_exca(struct class_device *class_dev, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) 	struct i82365_socket *s = container_of(class_dev, struct i82365_socket, socket.dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) 	unsigned short sock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) 	ssize_t ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) 	unsigned long flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) 	sock = s->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) 	ISA_LOCK(sock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) 	for (i = 0; i < 0x40; i += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) 		ret += sprintf(buf, "%02x %02x %02x %02x%s",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) 			       i365_get(sock,i), i365_get(sock,i+1),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) 			       i365_get(sock,i+2), i365_get(sock,i+3),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) 			       ((i % 16) == 12) ? "\n" : " ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) 		buf += ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) 	ISA_UNLOCK(sock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) static CLASS_DEVICE_ATTR(exca, S_IRUGO, show_exca, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) static CLASS_DEVICE_ATTR(info, S_IRUGO, show_info, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) /* this is horribly ugly... proper locking needs to be done here at 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153)  * some time... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) #define LOCKED(x) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) 	int retval; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) 	unsigned long flags; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 	spin_lock_irqsave(&isa_lock, flags); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) 	retval = x; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) 	spin_unlock_irqrestore(&isa_lock, flags); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) 	return retval; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) 	
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) static int pcic_get_status(struct pcmcia_socket *s, u_int *value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) 	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) 	if (socket[sock].flags & IS_ALIVE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) 		*value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) 	LOCKED(i365_get_status(sock, value));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) static int pcic_set_socket(struct pcmcia_socket *s, socket_state_t *state)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) 	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) 	if (socket[sock].flags & IS_ALIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) 	LOCKED(i365_set_socket(sock, state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) static int pcic_set_io_map(struct pcmcia_socket *s, struct pccard_io_map *io)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) 	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) 	if (socket[sock].flags & IS_ALIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) 	LOCKED(i365_set_io_map(sock, io));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) static int pcic_set_mem_map(struct pcmcia_socket *s, struct pccard_mem_map *mem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) 	unsigned int sock = container_of(s, struct i82365_socket, socket)->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) 	if (socket[sock].flags & IS_ALIVE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) 	LOCKED(i365_set_mem_map(sock, mem));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) static int pcic_init(struct pcmcia_socket *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) 	struct resource res = { .start = 0, .end = 0x1000 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) 	pccard_io_map io = { 0, 0, 0, 0, 1 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) 	pccard_mem_map mem = { .res = &res, };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) 	for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) 		io.map = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) 		pcic_set_io_map(s, &io);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) 	for (i = 0; i < 5; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) 		mem.map = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) 		pcic_set_mem_map(s, &mem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) static struct pccard_operations pcic_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) 	.init			= pcic_init,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) 	.get_status		= pcic_get_status,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) 	.set_socket		= pcic_set_socket,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) 	.set_io_map		= pcic_set_io_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) 	.set_mem_map		= pcic_set_mem_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) /*====================================================================*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) static struct platform_driver i82365_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) 		.name = "i82365",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) static struct platform_device *i82365_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) static int __init init_i82365(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)     int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)     ret = platform_driver_register(&i82365_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246)     if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) 	goto err_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249)     i82365_device = platform_device_alloc("i82365", 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)     if (i82365_device) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) 	    ret = platform_device_add(i82365_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) 	    if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) 		    platform_device_put(i82365_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254)     } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) 	    ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257)     if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) 	goto err_driver_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260)     printk(KERN_INFO "Intel ISA PCIC probe: ");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261)     sockets = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263)     isa_probe();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265)     if (sockets == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) 	printk("not found.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) 	ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) 	goto err_dev_unregister;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271)     /* Set up interrupt handler(s) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272)     if (grab_irq != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) 	ret = request_irq(cs_irq, pcic_interrupt, 0, "i82365", pcic_interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275)     if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) 	goto err_socket_release;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)     /* register sockets with the pcmcia core */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279)     for (i = 0; i < sockets; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) 	    socket[i].socket.dev.parent = &i82365_device->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) 	    socket[i].socket.ops = &pcic_operations;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) 	    socket[i].socket.resource_ops = &pccard_nonstatic_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) 	    socket[i].socket.owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) 	    socket[i].number = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) 	    ret = pcmcia_register_socket(&socket[i].socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) 	    if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) 		    socket[i].flags |= IS_REGISTERED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290)     /* Finally, schedule a polling interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291)     if (poll_interval != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) 	timer_setup(&poll_timer, pcic_interrupt_wrapper, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293)     	poll_timer.expires = jiffies + poll_interval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) 	add_timer(&poll_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296)     
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297)     return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) err_socket_release:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)     for (i = 0; i < sockets; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) 	/* Turn off all interrupt sources! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) 	i365_set(i, I365_CSCINT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) 	release_region(socket[i].ioaddr, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) err_dev_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305)     platform_device_unregister(i82365_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306)     release_region(i365_base, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)     if (i82365_pnpdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) 	pnp_disable_dev(i82365_pnpdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) err_driver_unregister:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312)     platform_driver_unregister(&i82365_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) err_out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)     return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) } /* init_i82365 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) static void __exit exit_i82365(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319)     int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321)     for (i = 0; i < sockets; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) 	    if (socket[i].flags & IS_REGISTERED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) 		    pcmcia_unregister_socket(&socket[i].socket);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)     platform_device_unregister(i82365_device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326)     if (poll_interval != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) 	del_timer_sync(&poll_timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)     if (grab_irq != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) 	free_irq(cs_irq, pcic_interrupt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)     for (i = 0; i < sockets; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) 	/* Turn off all interrupt sources! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) 	i365_set(i, I365_CSCINT, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) 	release_region(socket[i].ioaddr, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334)     }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)     release_region(i365_base, 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) #ifdef CONFIG_PNP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337)     if (i82365_pnpdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338)     		pnp_disable_dev(i82365_pnpdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340)     platform_driver_unregister(&i82365_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) } /* exit_i82365 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) module_init(init_i82365);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) module_exit(exit_i82365);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) MODULE_LICENSE("Dual MPL/GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) /*====================================================================*/