First cut at bringing NEC PC98 original pccard bridge code back into

FreeBSD.  This code doesn't work just yet, but does compile.  We need
to start indirecting via the cinfo pointers, rather than directly
calling pcic_*.  There may be other issues as well, but you gotta
start somewhere.

Obtained from: PAO3
This commit is contained in:
Warner Losh 2001-04-19 00:04:08 +00:00
parent d04d50d1f7
commit 7402675de4
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=75687
4 changed files with 371 additions and 46 deletions

View File

@ -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 */
/*

View File

@ -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)

View File

@ -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

View File

@ -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);