summaryrefslogtreecommitdiffstats
path: root/sys/pccard
diff options
context:
space:
mode:
authornate <nate@FreeBSD.org>1996-02-21 23:20:21 +0000
committernate <nate@FreeBSD.org>1996-02-21 23:20:21 +0000
commit3f825d95474a8cf312608785fad3b15deb2f486a (patch)
tree9e776d3327ba0212196369625f4d5b82ffa8d5d5 /sys/pccard
parent98df79c16931ef02ab7229300615dca86fad47dc (diff)
downloadFreeBSD-src-3f825d95474a8cf312608785fad3b15deb2f486a.zip
FreeBSD-src-3f825d95474a8cf312608785fad3b15deb2f486a.tar.gz
Updated PC-CARD support to contain most of the code from the latest
Japanese BSD-Nomad release. Reviewed by: phk Submitted by: hosokawa@mt.cs.keio.ac.jp and the rest of the Nomads
Diffstat (limited to 'sys/pccard')
-rw-r--r--sys/pccard/card.h10
-rw-r--r--sys/pccard/cardinfo.h10
-rw-r--r--sys/pccard/i82365.h6
-rw-r--r--sys/pccard/pccard.c38
-rw-r--r--sys/pccard/pcic.c115
5 files changed, 160 insertions, 19 deletions
diff --git a/sys/pccard/card.h b/sys/pccard/card.h
index 575253f..424098b 100644
--- a/sys/pccard/card.h
+++ b/sys/pccard/card.h
@@ -122,6 +122,16 @@ struct power {
};
/*
+ * Beep parameters
+ */
+#define PCCARD_BEEP_PITCH0 1600 /* inserted/removed */
+#define PCCARD_BEEP_DURATION0 20
+#define PCCARD_BEEP_PITCH1 1200 /* successed */
+#define PCCARD_BEEP_DURATION1 40
+#define PCCARD_BEEP_PITCH2 3200 /* failed */
+#define PCCARD_BEEP_DURATION2 40
+
+/*
* Other system limits
*/
#define MAXSLOT 16
diff --git a/sys/pccard/cardinfo.h b/sys/pccard/cardinfo.h
index 575253f..424098b 100644
--- a/sys/pccard/cardinfo.h
+++ b/sys/pccard/cardinfo.h
@@ -122,6 +122,16 @@ struct power {
};
/*
+ * Beep parameters
+ */
+#define PCCARD_BEEP_PITCH0 1600 /* inserted/removed */
+#define PCCARD_BEEP_DURATION0 20
+#define PCCARD_BEEP_PITCH1 1200 /* successed */
+#define PCCARD_BEEP_DURATION1 40
+#define PCCARD_BEEP_PITCH2 3200 /* failed */
+#define PCCARD_BEEP_DURATION2 40
+
+/*
* Other system limits
*/
#define MAXSLOT 16
diff --git a/sys/pccard/i82365.h b/sys/pccard/i82365.h
index a6cec01..c50c0f9 100644
--- a/sys/pccard/i82365.h
+++ b/sys/pccard/i82365.h
@@ -37,10 +37,12 @@
#define PCIC_IBM 1 /* IBM clone */
#define PCIC_VLSI 2 /* VLSI chip */
#define PCIC_PD672X 3 /* Cirrus logic 627x */
-#define PCIC_PD6710 4
+#define PCIC_PD6710 4 /* Cirrus logic 6710 */
#define PCIC_CL6729 5
#define PCIC_VG468 6
#define PCIC_VG469 7
+#define PCIC_RF5C396 8 /* Ricoh RF5C396 */
+#define PCIC_IBM_KING 9 /* IBM KING PCMCIA Controller */
/*
* Address of the controllers. Each controller can manage
* two PCMCIA slots. Up to 8 slots are supported in total.
@@ -89,6 +91,7 @@
#define PCIC_INTEL1 0x83 /* Intel 82365SL Rev. 1; Both Memory and I/O */
#define PCIC_IBM1 0x88 /* IBM PCIC clone; Both Memory and I/O */
#define PCIC_IBM2 0x89 /* IBM PCIC clone; Both Memory and I/O */
+#define PCIC_IBM3 0x8a /* IBM KING PCIC clone; Both Memory and I/O */
/* For Interface Status register (PCIC_STATUS) */
#define PCIC_VPPV 0x80 /* Vpp_valid */
@@ -106,6 +109,7 @@
#define PCIC_VCC 0x18 /* Vcc control bits */
#define PCIC_VCC_5V 0x10 /* 5 volts */
#define PCIC_VCC_3V 0x18 /* 3 volts */
+#define PCIC_VCC_5V_KING 0x14 /* 5 volts for KING PCIC */
#define PCIC_VPP 0x0C /* Vpp control bits */
#define PCIC_VPP_5V 0x01 /* 5 volts */
#define PCIC_VPP_12V 0x02 /* 12 volts */
diff --git a/sys/pccard/pccard.c b/sys/pccard/pccard.c
index 0c0c452..fd99cdf 100644
--- a/sys/pccard/pccard.c
+++ b/sys/pccard/pccard.c
@@ -55,7 +55,7 @@
#include <pccard/driver.h>
#include <pccard/slot.h>
-
+#include <i386/include/laptops.h>
extern struct kern_devconf kdc_cpu0;
@@ -144,6 +144,7 @@ pccard_add_driver(struct pccard_drv *dp)
printf("Driver %s already loaded\n", dp->name);
return;
}
+ printf("pccard driver %s added\n", dp->name);
dp->next = drivers;
drivers = dp;
}
@@ -357,12 +358,17 @@ pccard_alloc_intr(int imask, inthand2_t *hand, int unit, int *maskp)
int irq;
unsigned int mask;
+#if 0
+ /*
+ * this overrides IRQ masks specified by pccardd,
+ * so I removed this code. (hosokawa@mt.cs.keio.ac.jp)
+ */
imask = 1<< 3;
imask |= 1<< 5;
imask |= 1<< 9;
imask |= 1<<11;
imask |= 1<<15;
-
+#endif
for (irq = 1; irq < 16; irq++) {
mask = 1ul << irq;
@@ -542,6 +548,17 @@ inserted(void *arg)
}
/*
+ * Insert/Remove beep
+ */
+
+static int beepok = 1;
+
+static void enable_beep(void *dummy)
+{
+ beepok = 1;
+}
+
+/*
* Card event callback. Called at splhigh to prevent
* device interrupts from interceding.
*/
@@ -566,12 +583,18 @@ int s;
sp->state = empty;
splx(s);
printf("Card removed, slot %d\n", sp->slot);
+ sysbeep(PCCARD_BEEP_PITCH0, PCCARD_BEEP_DURATION0);
+ beepok = 0;
+ timeout(enable_beep, (void *)NULL, hz/5);
selwakeup(&sp->selp);
}
break;
case card_inserted:
sp->insert_seq = 1;
timeout(inserted, (void *)sp, hz/4);
+ sysbeep(PCCARD_BEEP_PITCH0, PCCARD_BEEP_DURATION0);
+ beepok = 0;
+ timeout(enable_beep, (void *)NULL, hz/5);
break;
}
}
@@ -733,7 +756,7 @@ crdwrite(dev_t dev, struct uio *uio, int ioflag)
static int
crdioctl(dev_t dev, int cmd, caddr_t data, int fflag, struct proc *p)
{
- int s;
+ int s, err;
struct slot *sp = pccard_slots[minor(dev)];
struct mem_desc *mp;
struct io_desc *ip;
@@ -853,7 +876,12 @@ crdioctl(dev_t dev, int cmd, caddr_t data, int fflag, struct proc *p)
case PIOCSDRV:
if (suser(p->p_ucred, &p->p_acflag))
return(EPERM);
- return(allocate_driver(sp, (struct drv_desc *)data));
+ err = allocate_driver(sp, (struct drv_desc *)data);
+ if (!err)
+ sysbeep(PCCARD_BEEP_PITCH1, PCCARD_BEEP_DURATION1);
+ else
+ sysbeep(PCCARD_BEEP_PITCH2, PCCARD_BEEP_DURATION2);
+ return err;
}
return(0);
}
@@ -929,5 +957,3 @@ crd_drvinit(void *unused)
}
SYSINIT(crddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,crd_drvinit,NULL)
-
-
diff --git a/sys/pccard/pcic.c b/sys/pccard/pcic.c
index 5fe35ad..30b97d8 100644
--- a/sys/pccard/pcic.c
+++ b/sys/pccard/pcic.c
@@ -59,6 +59,8 @@
#include <pccard/driver.h>
#include <pccard/slot.h>
+#include <i386/include/laptops.h>
+
extern struct kern_devconf kdc_pccard0;
struct kern_devconf kdc_pcic[PCIC_MAX_SLOTS] = {
@@ -363,40 +365,56 @@ pcic_io(struct slot *slotp, int win)
struct pcic_slot *sp = slotp->cdata;
struct io_desc *ip = &slotp->io[win];
- if (win) {
+ switch (win) {
+ case 0:
mask = PCIC_IO0_EN;
reg = PCIC_IO0;
- } else {
+ break;
+ case 1:
mask = PCIC_IO1_EN;
reg = PCIC_IO1;
+ break;
+ default:
+ panic("Illegal PCIC I/O window request!");
}
if (ip->flags & IODF_ACTIVE) {
- unsigned char x = 0;
+ unsigned char x, ioctlv;
+#ifdef PCIC_DEBUG
+printf("Map I/O 0x%x (size 0x%x) on Window %d\n", ip->start, ip->size, win);
+#endif /* PCIC_DEBUG */
putw (sp, reg, ip->start);
putw (sp, reg+2, ip->start+ip->size-1);
+ x = 0;
if (ip->flags & IODF_ZEROWS)
- x = PCIC_IO_0WS;
+ x |= PCIC_IO_0WS;
if (ip->flags & IODF_WS)
x |= PCIC_IO_WS;
if (ip->flags & IODF_CS16)
x |= PCIC_IO_CS16;
- else if (ip->flags & IODF_16BIT)
+ if (ip->flags & IODF_16BIT)
x |= PCIC_IO_16BIT;
/*
* Extract the current flags and merge with new flags.
* Flags for window 0 in lower nybble, and in upper nybble
* for window 1.
*/
- if (win)
- putb(sp, PCIC_IOCTL, (x << 4) |
- (getb(sp, PCIC_IOCTL) & 0xF));
- else
- putb(sp, PCIC_IOCTL, x | (getb(sp, PCIC_IOCTL) & 0xF0));
+ ioctlv = getb(sp, PCIC_IOCTL);
+ DELAY(100);
+ switch (win) {
+ case 0:
+ putb(sp, PCIC_IOCTL, x | (ioctlv & 0xf0));
+ break;
+ case 1:
+ putb(sp, PCIC_IOCTL, (x << 4) | (ioctlv & 0xf));
+ break;
+ }
+ DELAY(100);
setb (sp, PCIC_ADDRWINE, mask);
DELAY(100);
} else {
clrb (sp, PCIC_ADDRWINE, mask);
+ DELAY(100);
putw (sp, reg, 0);
putw (sp, reg + 2, 0);
}
@@ -408,6 +426,14 @@ pcic_io(struct slot *slotp, int win)
* For each available slot, allocate a PC-CARD slot.
*/
+/*
+ * VLSI 82C146 has incompatibilities about the I/O address
+ * of slot 1. If it's the only PCIC whose vendor ID is 0x84,
+ * I want to remove this #define and corresponding #ifdef's.
+ * HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ */
+#define VLSI_SLOT1 1
+
int
pcic_probe ()
{
@@ -415,6 +441,9 @@ pcic_probe ()
struct slot *slotp;
struct pcic_slot *sp;
unsigned char c;
+#ifdef VLSI_SLOT1
+ static int vs = 0;
+#endif /* VLSI_SLOT1 */
/*
* Initialise controller information structure.
@@ -439,9 +468,21 @@ pcic_probe ()
* Initialise the PCIC slot table.
*/
if (slot < 4) {
+#ifdef VLSI_SLOT1
+ if (slot == 1 && vs) {
+ sp->index = PCIC_INDEX_0 + 4;
+ sp->data = PCIC_DATA_0 + 4;
+ sp->offset = PCIC_SLOT_SIZE << 1;
+ } else {
+ sp->index = PCIC_INDEX_0;
+ sp->data = PCIC_DATA_0;
+ sp->offset = slot * PCIC_SLOT_SIZE;
+ }
+#else /* VLSI_SLOT1 */
sp->index = PCIC_INDEX_0;
sp->data = PCIC_DATA_0;
sp->offset = slot * PCIC_SLOT_SIZE;
+#endif /* VLSI_SLOT1 */
} else {
sp->index = PCIC_INDEX_1;
sp->data = PCIC_DATA_1;
@@ -474,18 +515,34 @@ pcic_probe ()
PCIC_VG469 : PCIC_VG468 ;
clrb(sp, 0x3A, 0x40);
}
+
+ /*
+ * Check for RICOH RF5C396 PCMCIA Controller
+ */
+ c = getb (sp, 0x3a);
+ if (c == 0xb2) {
+ sp->controller = PCIC_RF5C396;
+ }
+
break;
/*
* VLSI chips.
*/
case 0x84:
sp->controller = PCIC_VLSI;
+#ifdef VLSI_SLOT1
+ vs = 1;
+#endif /* VLSI_SLOT1 */
break;
case 0x88:
case 0x89:
sp->controller = PCIC_IBM;
sp->revision = c & 1;
break;
+ case 0x8a:
+ sp->controller = PCIC_IBM_KING;
+ sp->revision = c & 1;
+ break;
default:
continue;
}
@@ -511,6 +568,9 @@ pcic_probe ()
case PCIC_IBM:
cinfo.name = "IBM PCIC";
break;
+ case PCIC_IBM_KING:
+ cinfo.name = "IBM KING PCMCIA Controller";
+ break;
case PCIC_PD672X:
cinfo.name = "Cirrus Logic PD672X";
break;
@@ -523,15 +583,23 @@ pcic_probe ()
case PCIC_VG469:
cinfo.name = "Vadem 469";
break;
+ case PCIC_RF5C396:
+ cinfo.name = "Ricoh RF5C396";
+ break;
+ case PCIC_VLSI:
+ cinfo.name = "VLSI 82C146";
+ break;
default:
cinfo.name = "Unknown!";
break;
}
+#ifndef PCIC_NOCLRREGS
/*
* clear out the registers.
*/
for (i = 2; i < 0x40; i++)
putb(sp, i, 0);
+#endif /* PCIC_NOCLRREGS */
/*
* OK it seems we have a PCIC or lookalike.
* Allocate a slot and initialise the data structures.
@@ -621,7 +689,11 @@ pcic_power(struct slot *slotp)
switch(sp->controller) {
case PCIC_PD672X:
case PCIC_PD6710:
+ case PCIC_VG468:
case PCIC_VG469:
+ case PCIC_RF5C396:
+ case PCIC_VLSI:
+ case PCIC_IBM_KING:
switch(slotp->pwr.vpp) {
default:
return(EINVAL);
@@ -641,20 +713,31 @@ pcic_power(struct slot *slotp)
case 0:
break;
case 33:
+ if (sp->controller == PCIC_IBM_KING) {
+ reg |= PCIC_VCC_5V_KING;
+ break;
+ }
reg |= PCIC_VCC_5V;
- if (sp->controller == PCIC_VG469)
+ if ((sp->controller == PCIC_VG468)||
+ (sp->controller == PCIC_VG469))
setb(sp, 0x2f, 0x03) ;
else
setb(sp, 0x16, 0x02);
break;
case 50:
+ if (sp->controller == PCIC_IBM_KING) {
+ reg |= PCIC_VCC_5V_KING;
+ break;
+ }
reg |= PCIC_VCC_5V;
- if (sp->controller == PCIC_VG469)
+ if ((sp->controller == PCIC_VG468)||
+ (sp->controller == PCIC_VG469))
clrb(sp, 0x2f, 0x03) ;
else
clrb(sp, 0x16, 0x02);
break;
}
+ break;
}
putb (sp, PCIC_POWER, reg);
DELAY(300*1000);
@@ -695,25 +778,33 @@ pcic_reset(void *chan)
case 0: /* Something funny happended on the way to the pub... */
return;
case 1: /* Assert reset */
+#if 0
printf("R");
+#endif
clrb (sp, PCIC_INT_GEN, PCIC_CARDRESET);
slotp->insert_seq = 2;
timeout(pcic_reset, (void*) slotp, hz/4);
return;
case 2: /* Deassert it again */
+#if 0
printf("r");
+#endif
setb (sp, PCIC_INT_GEN, PCIC_CARDRESET|PCIC_IOCARD);
slotp->insert_seq = 3;
timeout(pcic_reset, (void*) slotp, hz/4);
return;
case 3: /* Wait if card needs more time */
if (!getb(sp, PCIC_STATUS) & PCIC_READY) {
+#if 0
printf("_");
+#endif
timeout(pcic_reset, (void*) slotp, hz/10);
return;
}
}
+#if 0
printf(".\n");
+#endif
slotp->insert_seq = 0;
if (sp->controller == PCIC_PD672X || sp->controller == PCIC_PD6710) {
putb(sp, PCIC_TIME_SETUP0, 0x1);
OpenPOWER on IntegriCloud