
/* Support for the Intel 82365 PCMCIA interface chip.  See the Intel
   Mobile Computer Products data book for more information. 

   This code used to live in dl650.c, an Ethernet driver for a PCMCIA
   Ethernet card.  It still is specific the Ethernet, but we have more
   than one PCMCIA interface chip to support and this splitting makes
   things cleaner. */

static char *version = 
  "82365.c:v0.99-14 based on 12/5/93 pcmcia.c:v0.99-13 D.Hinds (dhinds@allegro.stanford.edu)\n";

/* Slight dependence on the Ethernet driver for the DL650. */

extern int ei_debug;

#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/errno.h>
#include "dev.h"
#include <asm/system.h>
#include <asm/io.h>
#include "82365.h"

/* In dl650.c, delays 'len' clock ticks. */

void delay(int len);

#define I365_SET(r, d) \
  do { outb_p((r)+off, base); outb_p((d), base+1); } while (0)
#define I365_SET_PAIR(r, d) \
  do { I365_SET((r), (d) & 0xFF); I365_SET((r)+1, (d) >> 8); } while (0)

/* See if this laptop is using an Intel 82365 PCMCIA controller.  If
   it is, configure it for use with the DL650 Ethernet controller and
   return 0.  Otherwise, return ENODEV. */

int probe_for_82365(struct device *dev)
{
	int base, off, ioaddr, id;
	int we_found_it = 0;

	if (ei_debug)
	  printk(version);

	/* This will probe up to four 82365SL's */
	for (base = I365_BASE; base < I365_BASE+4; base += 2) {
		for (off = 0; off < 0x100; off += 0x40) {
			/* probe for Intel 82365SL */
			outb_p(I365_IDENT+off, base); id = inb_p(base+1);
			if ((id != 0x82) && (id != 0x83)) return ENODEV;
			/* Check for socketed card */
			outb_p(I365_STATUS+off, base);
			if ((inb_p(base+1) & CS_DETECT) != CS_DETECT) continue;
			we_found_it = 1;
			break; /* We found it. */
		}
	}
	if (!we_found_it)
		return ENODEV;

	/* Shut down, then turn on the card */
	I365_SET(I365_POWER, PWR_OFF);
	delay(1);
	I365_SET(I365_POWER, (PWR_OUT | PWR_NORESET | VCC_5V));
	delay(2);

#if defined(DE_SHMEM)
	dev->mem_start = DE_SHMEM;
#else
	if (dev->mem_start == 0) dev->mem_start = 0xD6000L;
#endif
	ioaddr = dev->base_addr;

	I365_SET_PAIR(I365_IO_0+W_START, ioaddr);
	I365_SET_PAIR(I365_IO_0+W_STOP, ioaddr+0x0F);
	I365_SET_PAIR(I365_IO_1+W_START, ioaddr+0x10);
	I365_SET_PAIR(I365_IO_1+W_STOP, ioaddr+0x1F);
	/* The 8390 ports are 8-bit, but the DMA port is 16-bit */
	I365_SET(I365_IOCTL, (IOCTL_1_CS16 | IOCTL_1_16BIT));
	/* Set up memory window 0 for the PROM */
	I365_SET_PAIR(I365_MEM_0+W_START, dev->mem_start >> 12);
	I365_SET_PAIR(I365_MEM_0+W_STOP, dev->mem_start >> 12);
	I365_SET_PAIR(I365_MEM_0+W_OFF, (((-dev->mem_start >> 12) & 0x0FFF) | 0x5000));
	/* Turn on I/O and memory windows */
	I365_SET(I365_ADDRWIN, (ENA_IO_1 | ENA_IO_0 | ENA_MEM_0));
	/* Turn on card IRQ */
	I365_SET(I365_INTCTL, (PC_RESET | PC_IOCARD | dev->irq));
	return 0;
}
