diff options
| author | Warner Losh <imp@FreeBSD.org> | 2001-04-19 00:04:08 +0000 |
|---|---|---|
| committer | Warner Losh <imp@FreeBSD.org> | 2001-04-19 00:04:08 +0000 |
| commit | 7402675de47e0dea7d86b8dc36bb5afea8fe6f8c (patch) | |
| tree | e6bb29a0c74db3818e9f3ef1c87bd9581bd3b5ce | |
| parent | d04d50d1f71224c22a46fad6f19255c16bf09a7e (diff) | |
Notes
| -rw-r--r-- | sys/pccard/i82365.h | 2 | ||||
| -rw-r--r-- | sys/pccard/pcic.c | 357 | ||||
| -rw-r--r-- | sys/pccard/pcic98reg.h | 56 | ||||
| -rw-r--r-- | sys/pccard/slot.h | 2 |
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); |
