aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2001-04-19 00:04:08 +0000
committerWarner Losh <imp@FreeBSD.org>2001-04-19 00:04:08 +0000
commit7402675de47e0dea7d86b8dc36bb5afea8fe6f8c (patch)
treee6bb29a0c74db3818e9f3ef1c87bd9581bd3b5ce
parentd04d50d1f71224c22a46fad6f19255c16bf09a7e (diff)
Notes
-rw-r--r--sys/pccard/i82365.h2
-rw-r--r--sys/pccard/pcic.c357
-rw-r--r--sys/pccard/pcic98reg.h56
-rw-r--r--sys/pccard/slot.h2
4 files changed, 371 insertions, 46 deletions
diff --git a/sys/pccard/i82365.h b/sys/pccard/i82365.h
index 20b2c09eaa75..e8ef822813c6 100644
--- a/sys/pccard/i82365.h
+++ b/sys/pccard/i82365.h
@@ -46,8 +46,8 @@
#define PCIC_VG469 8 /* Vadem 469 */
#define PCIC_RF5C396 9 /* Ricoh RF5C396 */
#define PCIC_IBM_KING 10 /* IBM KING PCMCIA Controller */
-/* These last two aren't in normal freebsd */
#define PCIC_PC98 11 /* NEC PC98 PCMCIA Controller */
+/* These last ones aren't in normal freebsd */
#define PCIC_TI1130 12 /* TI PCI1130 CardBus */
/*
diff --git a/sys/pccard/pcic.c b/sys/pccard/pcic.c
index 82e53ad1a6bf..4fd36db5d338 100644
--- a/sys/pccard/pcic.c
+++ b/sys/pccard/pcic.c
@@ -38,6 +38,12 @@
#include <pccard/i82365.h>
#include <pccard/cardinfo.h>
#include <pccard/slot.h>
+#ifdef PC98
+#include <pccard/pcic98reg.h>
+#ifndef PCIC98_IOBASE
+#define PCIC98_IOBASE 0x80d0
+#endif
+#endif /* PC98 */
/* Get pnp IDs */
#include <isa/isavar.h>
@@ -51,6 +57,7 @@
static driver_intr_t pcicintr;
static int pcic_ioctl(struct slot *, int, caddr_t);
static int pcic_power(struct slot *);
+static void pcic_mapirq(struct slot *, int);
static timeout_t pcic_reset;
static void pcic_resume(struct slot *);
static void pcic_disable(struct slot *);
@@ -59,6 +66,16 @@ static struct callout_handle pcictimeout_ch
= CALLOUT_HANDLE_INITIALIZER(&pcictimeout_ch);
static int pcic_memory(struct slot *, int);
static int pcic_io(struct slot *, int);
+#ifdef PC98
+/* local functions for PC-98 Original PC-Card controller */
+static int pcic98_power(struct slot *);
+static void pcic98_mapirq(struct slot *, int);
+static int pcic98_memory(struct slot *, int);
+static int pcic98_io(struct slot *, int);
+static timeout_t pcic98_reset;
+static void pcic98_disable(struct slot *);
+static void pcic98_resume(struct slot *);
+#endif /* PC98 */
/*
* Per-slot data table.
@@ -90,6 +107,9 @@ static struct isa_pnp_id pcic_ids[] = {
};
static int validunits = 0;
+#ifdef PC98
+static u_char pcic98_last_reg1;
+#endif /* PC98 */
#define GET_UNIT(d) *(int *)device_get_softc(d)
#define SET_UNIT(d,u) *(int *)device_get_softc(d) = (u)
@@ -106,7 +126,8 @@ static char *bridges[] =
"Vadem 468",
"Vadem 469",
"Ricoh RF5C396",
- "IBM KING PCMCIA Controller"
+ "IBM KING PCMCIA Controller",
+ "PC-98 Original"
};
/*
@@ -306,6 +327,7 @@ pcic_probe(device_t dev)
/*
* Initialise controller information structure.
*/
+ cinfo.mapirq = pcic_mapirq;
cinfo.mapmem = pcic_memory;
cinfo.mapio = pcic_io;
cinfo.ioctl = pcic_ioctl;
@@ -457,6 +479,30 @@ pcic_probe(device_t dev)
}
}
bus_release_resource(dev, SYS_RES_IOPORT, rid, r);
+#ifdef PC98
+ if (validslots == 0) {
+ sp = &pcic_slots[validunits * PCIC_CARD_SLOTS];
+ if (inb(PCIC98_REG0) != 0xff) {
+ sp->controller = PCIC_PC98;
+ sp->revision = 0;
+ cinfo.mapmem = pcic98_memory;
+ cinfo.mapio = pcic98_io;
+ cinfo.power = pcic98_power;
+ cinfo.mapirq = pcic98_mapirq;
+ cinfo.reset = pcic98_reset;
+ cinfo.disable = pcic98_disable;
+ cinfo.resume = pcic98_resume;
+ cinfo.maxmem = 1;
+#if 0
+ cinfo.maxio = 1;
+#else
+ cinfo.maxio = 2; /* fake for UE2212 LAN card */
+#endif
+ validslots++;
+ /* XXX Do I need to allocated the port resources? */
+ }
+ }
+#endif /* PC98 */
return(validslots ? 0 : ENXIO);
}
@@ -537,18 +583,32 @@ pcic_attach(device_t dev)
if (sp->slt == NULL)
continue;
- do_mgt_irq(sp, irq);
+#ifdef PC98
+ if (sp->controller == PCIC_PC98) {
+ pcic98_last_reg1 = inb(PCIC98_REG1);
+ if (pcic98_last_reg1 & PCIC98_CARDEXIST) {
+ /* PCMCIA card exist */
+ sp->slt->laststate = sp->slt->state = filled;
+ pccard_event(sp->slt, card_inserted);
+ } else {
+ sp->slt->laststate = sp->slt->state = empty;
+ }
+ } else
+#endif /* PC98 */
+ {
+ do_mgt_irq(sp, irq);
- /* Check for changes */
- setb(sp, PCIC_POWER, PCIC_PCPWRE| PCIC_DISRST);
- stat = sp->getb(sp, PCIC_STATUS);
- if (bootverbose)
- printf("stat is %x\n", stat);
- if ((stat & PCIC_CD) != PCIC_CD) {
- sp->slt->laststate = sp->slt->state = empty;
- } else {
- sp->slt->laststate = sp->slt->state = filled;
- pccard_event(sp->slt, card_inserted);
+ /* Check for changes */
+ setb(sp, PCIC_POWER, PCIC_PCPWRE| PCIC_DISRST);
+ stat = sp->getb(sp, PCIC_STATUS);
+ if (bootverbose)
+ printf("stat is %x\n", stat);
+ if ((stat & PCIC_CD) != PCIC_CD) {
+ sp->slt->laststate = sp->slt->state = empty;
+ } else {
+ sp->slt->laststate = sp->slt->state = filled;
+ pccard_event(sp->slt, card_inserted);
+ }
}
sp->slt->irq = irq;
}
@@ -765,17 +825,37 @@ pcicintr(void *arg)
struct pcic_slot *sp = &pcic_slots[unit * PCIC_CARD_SLOTS];
s = splhigh();
- for (slot = 0; slot < PCIC_CARD_SLOTS; slot++, sp++) {
- if (sp->slt && (chg = sp->getb(sp, PCIC_STAT_CHG)) != 0) {
- if (bootverbose)
- printf("Slot %d chg = 0x%x\n", slot, chg);
- if (chg & PCIC_CDTCH) {
- if ((sp->getb(sp, PCIC_STATUS) & PCIC_CD) ==
- PCIC_CD) {
- pccard_event(sp->slt, card_inserted);
- } else {
- pcic_disable(sp->slt);
- pccard_event(sp->slt, card_removed);
+#ifdef PC98
+ if (sp->controller == PCIC_PC98) {
+ u_char reg1;
+ /* Check for a card in this slot */
+ reg1 = inb(PCIC98_REG1);
+ if ((pcic98_last_reg1 ^ reg1) & PCIC98_CARDEXIST) {
+ pcic98_last_reg1 = reg1;
+ if (reg1 & PCIC98_CARDEXIST)
+ pccard_event(sp->slt, card_inserted);
+ else
+ pccard_event(sp->slt, card_removed);
+ }
+ } else
+#endif /* PC98 */
+ {
+ for (slot = 0; slot < PCIC_CARD_SLOTS; slot++, sp++) {
+ if (sp->slt &&
+ (chg = sp->getb(sp, PCIC_STAT_CHG)) != 0) {
+ if (bootverbose)
+ printf("Slot %d chg = 0x%x\n", slot,
+ chg);
+ if (chg & PCIC_CDTCH) {
+ if ((sp->getb(sp, PCIC_STATUS) &
+ PCIC_CD) == PCIC_CD) {
+ pccard_event(sp->slt,
+ card_inserted);
+ } else {
+ pcic_disable(sp->slt);
+ pccard_event(sp->slt,
+ card_removed);
+ }
}
}
}
@@ -798,6 +878,237 @@ pcic_resume(struct slot *slt)
}
}
+#ifdef PC98
+/*
+ * local functions for PC-98 Original PC-Card controller
+ */
+#define PCIC98_ALWAYS_128MAPPING 1 /* trick for using UE2212 */
+
+int pcic98_mode = 0; /* almost the same as the value in PCIC98_REG2 */
+
+static unsigned char reg_winsel = PCIC98_UNMAPWIN;
+static unsigned short reg_pagofs = 0;
+
+static int
+pcic98_memory(struct slot *slt, int win)
+{
+ struct mem_desc *mp = &slt->mem[win];
+ unsigned char x;
+
+ if (mp->flags & MDF_ACTIVE) {
+ /* slot = 0, window = 0, sys_addr = 0xda000, length = 8KB */
+ if ((unsigned long)mp->start != 0xda000) {
+ printf(
+ "sys_addr must be 0xda000. requested address = %p\n",
+ mp->start);
+ return(EINVAL);
+ }
+
+ /* omajinai ??? */
+ outb(PCIC98_REG0, 0);
+ x = inb(PCIC98_REG1);
+ x &= 0xfc;
+ x |= 0x02;
+ outb(PCIC98_REG1, x);
+ reg_winsel = inb(PCIC98_REG_WINSEL);
+ reg_pagofs = inw(PCIC98_REG_PAGOFS);
+ outb(PCIC98_REG_WINSEL, PCIC98_MAPWIN);
+ outw(PCIC98_REG_PAGOFS, (mp->card >> 13)); /* 8KB */
+
+ if (mp->flags & MDF_ATTR) {
+ outb(PCIC98_REG7, inb(PCIC98_REG7) | PCIC98_ATTRMEM);
+ }else{
+ outb(PCIC98_REG7, inb(PCIC98_REG7) & (~PCIC98_ATTRMEM));
+ }
+
+ outb(PCIC98_REG_WINSEL, PCIC98_MAPWIN);
+#if 0
+ if ((mp->flags & MDF_16BITS) == 1) { /* 16bit */
+ outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_8BIT));
+ }else{ /* 8bit */
+ outb(PCIC98_REG2, inb(PCIC98_REG2) | PCIC98_8BIT);
+ }
+#endif
+ } else { /* !(mp->flags & MDF_ACTIVE) */
+ outb(PCIC98_REG0, 0);
+ x = inb(PCIC98_REG1);
+ x &= 0xfc;
+ x |= 0x02;
+ outb(PCIC98_REG1, x);
+#if 0
+ outb(PCIC98_REG_WINSEL, PCIC98_UNMAPWIN);
+ outw(PCIC98_REG_PAGOFS, 0);
+#else
+ outb(PCIC98_REG_WINSEL, reg_winsel);
+ outw(PCIC98_REG_PAGOFS, reg_pagofs);
+#endif
+ }
+ return 0;
+}
+
+static int
+pcic98_io(struct slot *slt, int win)
+{
+ struct io_desc *ip = &slt->io[win];
+ unsigned char x;
+ unsigned short cardbase;
+ u_short ofst;
+
+ if (win != 0) {
+ /* ignore for UE2212 */
+ printf(
+ "pcic98:Illegal PCIC I/O window(%d) request! Ignored.\n", win);
+/* return(EINVAL);*/
+ return 0;
+ }
+
+ if (ip->flags & IODF_ACTIVE) {
+ x = inb(PCIC98_REG2) & 0x0f;
+#if 0
+ if (! (ip->flags & IODF_CS16))
+ x |= PCIC98_8BIT;
+#else
+ if (! (ip->flags & IODF_16BIT)) {
+ x |= PCIC98_8BIT;
+ pcic98_mode |= PCIC98_8BIT;
+ }
+#endif
+
+ ofst = ip->start & 0xf;
+ cardbase = ip->start & ~0xf;
+#ifndef PCIC98_ALWAYS_128MAPPING
+ if (ip->size + ofst > 16)
+#endif
+ { /* 128bytes mapping */
+ x |= PCIC98_MAP128;
+ pcic98_mode |= PCIC98_MAP128;
+ ofst |= ((cardbase & 0x70) << 4);
+ cardbase &= ~0x70;
+ }
+
+ x |= PCIC98_MAPIO;
+ outb(PCIC98_REG2, x);
+
+ outw(PCIC98_REG4, PCIC98_IOBASE); /* 98side I/O base */
+ outw(PCIC98_REG5, cardbase); /* card side I/O base */
+
+ if (bootverbose) {
+ printf("pcic98: I/O mapped 0x%04x(98) -> "
+ "0x%04x(Card) and width %d bytes\n",
+ PCIC98_IOBASE+ofst, ip->start, ip->size);
+ printf("pcic98: reg2=0x%02x reg3=0x%02x reg7=0x%02x\n",
+ inb(PCIC98_REG2), inb(PCIC98_REG3),
+ inb(PCIC98_REG7));
+ printf("pcic98: mode=%d\n", pcic98_mode);
+ }
+
+ ip->start = PCIC98_IOBASE + ofst;
+ } else {
+ outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_MAPIO));
+ pcic98_mode = 0;
+ }
+ return 0;
+}
+
+static int
+pcic98_power(struct slot *slt)
+{
+ unsigned char reg;
+
+ reg = inb(PCIC98_REG7) & (~PCIC98_VPP12V);
+ switch(slt->pwr.vpp) {
+ default:
+ return(EINVAL);
+ case 50:
+ break;
+ case 120:
+ reg |= PCIC98_VPP12V;
+ break;
+ }
+ outb(PCIC98_REG7, reg);
+ DELAY(100*1000);
+
+ reg = inb(PCIC98_REG2) & (~PCIC98_VCC3P3V);
+ switch(slt->pwr.vcc) {
+ default:
+ return(EINVAL);
+ case 33:
+ reg |= PCIC98_VCC3P3V;
+ break;
+ case 50:
+ break;
+ }
+ outb(PCIC98_REG2, reg);
+ DELAY(100*1000);
+ return 0;
+}
+
+static void
+pcic98_mapirq(struct slot *slt, int irq)
+{
+ u_char x;
+
+ switch (irq) {
+ case 3:
+ x = PCIC98_INT0;
+ break;
+ case 5:
+ x = PCIC98_INT1;
+ break;
+ case 6:
+ x = PCIC98_INT2;
+ break;
+ case 10:
+ x = PCIC98_INT4;
+ break;
+ case 12:
+ x = PCIC98_INT5;
+ break;
+ case 0: /* disable */
+ x = PCIC98_INTDISABLE;
+ break;
+ default:
+ printf("pcic98: illegal irq %d\n", irq);
+ return;
+ }
+#ifdef PCIC_DEBUG
+ printf("pcic98: irq=%d mapped.\n", irq);
+#endif
+ outb(PCIC98_REG3, x);
+}
+
+static void
+pcic98_reset(void *chan)
+{
+ struct slot *slt = chan;
+
+ outb(PCIC98_REG0, 0);
+ outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_MAPIO));
+ outb(PCIC98_REG3, PCIC98_INTDISABLE);
+#if 0
+/* pcic98_reset() is called after pcic98_power() */
+ outb(PCIC98_REG2, inb(PCIC98_REG2) & (~PCIC98_VCC3P3V));
+ outb(PCIC98_REG7, inb(PCIC98_REG7) & (~PCIC98_VPP12V));
+#endif
+ outb(PCIC98_REG1, 0);
+
+ selwakeup(&slt->selp);
+}
+
+static void
+pcic98_disable(struct slot *slt)
+{
+ /* null function */
+}
+
+static void
+pcic98_resume(struct slot *slt)
+{
+ /* XXX PCIC98 How ? */
+}
+#endif /* PC98 */
+/* end of local functions for PC-98 Original PC-Card controller */
+
static int
pcic_activate_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
diff --git a/sys/pccard/pcic98reg.h b/sys/pccard/pcic98reg.h
index e50862c9c5de..964f007e4c49 100644
--- a/sys/pccard/pcic98reg.h
+++ b/sys/pccard/pcic98reg.h
@@ -1,36 +1,36 @@
-/* $FreeBSD$ */
/*
- pcic98reg.h
-
- PC9801NS/A PCMCIA contorer routine conpatible to PCIC
- Noriyuki Hosobuchi 96.1.20
-
-*/
+ * pcic98reg.h
+ *
+ * PC9801 original PCMCIA controller code for NS/A,Ne,NX/C,NR/L.
+ * by Noriyuki Hosobuchi <hoso@ce.mbn.or.jp>
+ *
+ * $FreeBSD$
+ */
/*--- I/O port definition */
-#define PCIC98_REG0 0x0a8e /* byte */
-#define PCIC98_REG1 0x1a8e /* byte */
-#define PCIC98_REG2 0x2a8e /* byte */
-#define PCIC98_REG3 0x3a8e /* byte : Interrupt */
-#define PCIC98_REG4 0x4a8e /* word : PC98 side IO base */
-#define PCIC98_REG5 0x5a8e /* word : Card side IO base */
-#define PCIC98_REG6 0x7a8e /* byte */
+#define PCIC98_REG0 0x0a8e /* byte */
+#define PCIC98_REG1 0x1a8e /* byte */
+#define PCIC98_REG2 0x2a8e /* byte */
+#define PCIC98_REG3 0x3a8e /* byte : Interrupt */
+#define PCIC98_REG4 0x4a8e /* word : PC98 side I/O base */
+#define PCIC98_REG5 0x5a8e /* word : Card side I/O base */
+#define PCIC98_REG7 0x7a8e /* byte */
-#define PCIC98_REG_WINSEL 0x1e8e /* byte : win bank select register */
-#define PCIC98_REG_PAGOFS 0x0e8e /* word */
+#define PCIC98_REG_WINSEL 0x1e8e /* byte : win bank select register */
+#define PCIC98_REG_PAGOFS 0x0e8e /* word */
/* PC98_REG_WINSEL */
-#define PCIC98_MAPWIN 0x84 /* map Card on 0xda0000 - 0xdbffff */
+#define PCIC98_MAPWIN 0x84 /* map Card on 0xda0000 - 0xdbffff */
#define PCIC98_UNMAPWIN 0x00
/* PCIC98_REG1 */
#define PCIC98_CARDEXIST 0x08 /* 1:exist 0:not exist */
/* PCIC98_REG2 */
-#define PCIC98_IOMEMORY 0x80 /* 1:IO 0:Memory */
-#define PCIC98_MAPIO 0x40 /* 0:IO map 1:??? */
-#define PCIC98_8BIT 0x20 /* bit width 1:8bit 0:16bit */
-#define PCIC98_MAP128 0x10 /* IO map size 1:128byte 0:16byte */
+#define PCIC98_MAPIO 0x80 /* 1:I/O 0:Memory */
+#define PCIC98_IOTHROUGH 0x40 /* 0:I/O map 1:I/O addr-through */
+#define PCIC98_8BIT 0x20 /* bit width 1:8bit 0:16bit */
+#define PCIC98_MAP128 0x10 /* I/O map size 1:128byte 0:16byte */
#define PCIC98_VCC3P3V 0x02 /* Vcc 1:3.3V 0:5.0V */
/* PCIC98_REG3 */
@@ -41,6 +41,18 @@
#define PCIC98_INT5 (0xf8 + 0x5) /* INT5(IRQ12) */
#define PCIC98_INTDISABLE (0xf8 + 0x7) /* disable interrupt */
-/* PCIC98_REG6 */
+/* PCIC98_REG7 */
#define PCIC98_ATTRMEM 0x20 /* 1:attr mem 0:common mem */
#define PCIC98_VPP12V 0x10 /* Vpp 0:5V 1:12V */
+
+
+#ifdef KERNEL
+extern int pcic98_mode; /* in 'pccard/pcic.c' */
+#define pcic98_8bit_on() \
+ if (pcic98_mode & PCIC98_8BIT) \
+ outb(PCIC98_REG2, inb(PCIC98_REG2) | PCIC98_8BIT)
+#define pcic98_8bit_off() \
+ if (pcic98_mode & PCIC98_8BIT) \
+ outb(PCIC98_REG2, inb(PCIC98_REG2) & ~PCIC98_8BIT)
+#define pcic98_map128() (pcic98_mode & PCIC98_MAP128)
+#endif
diff --git a/sys/pccard/slot.h b/sys/pccard/slot.h
index 67f756df5617..0b95444812d3 100644
--- a/sys/pccard/slot.h
+++ b/sys/pccard/slot.h
@@ -54,6 +54,8 @@
*/
struct slot;
struct slot_ctrl {
+ void (*mapirq)(struct slot *, int);
+ /* Map irq */
int (*mapmem)(struct slot *, int);
/* Map memory */
int (*mapio)(struct slot *, int);