summaryrefslogtreecommitdiff
path: root/os/mpc/devpcmcia.c
diff options
context:
space:
mode:
authorKonstantin Kirik (snegovick) <snegovick@uprojects.org>2025-12-28 12:27:31 +0300
committerKonstantin Kirik (snegovick) <snegovick@uprojects.org>2025-12-28 12:27:31 +0300
commit78ee7d5717807e6ac779293d0d3c78341de6130a (patch)
treea43e3b0f61318ac45e6d907c7cc5bad2c6d7f497 /os/mpc/devpcmcia.c
parentbdaf46cf45bbb59261da245d548a179d95a42768 (diff)
Move existing boards into subdits split per arch
Diffstat (limited to 'os/mpc/devpcmcia.c')
-rw-r--r--os/mpc/devpcmcia.c1076
1 files changed, 0 insertions, 1076 deletions
diff --git a/os/mpc/devpcmcia.c b/os/mpc/devpcmcia.c
deleted file mode 100644
index 4c1d8311..00000000
--- a/os/mpc/devpcmcia.c
+++ /dev/null
@@ -1,1076 +0,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.h"
-
-/*
- * MPC821/3 PCMCIA driver (prototype)
- *
- * unlike the i82365 adapter, there isn't an offset register:
- * card addresses are simply the lower order 26 bits of the host address.
- *
- * to do:
- * split allocation of memory/attrib (all 26 bits valid) and io space (typically 10 or 12 bits)
- * correct config
- * interrupts and i/o space access
- * DMA?
- * power control
- */
-
-enum
-{
- Maxctlr= 1,
- Maxslot= 2,
- Slotashift= 16,
-
- /* pipr */
- Cbvs1= 1<<15,
- Cbvs2= 1<<14,
- Cbwp= 1<<13,
- Cbcd2= 1<<12,
- Cbcd1= 1<<11,
- Cbbvd2= 1<<10,
- Cbbvd1= 1<<9,
- Cbrdy= 1<<8,
-
- /* pscr and per */
- Cbvs1_c= 1<<15,
- Cbvs2_c= 1<<14,
- Cbwp_c= 1<<13,
- Cbcd2_c= 1<<12,
- Cbcd1_c= 1<<11,
- Cbbvd2_c= 1<<10,
- Cbbvd1_c= 1<<9,
- Cbrdy_l= 1<<7,
- Cbrdy_h= 1<<6,
- Cbrdy_r= 1<<5,
- Cbrdy_f= 1<<4,
-
- /* pgcr[n] */
- Cbdreq_int= 0<<14,
- Cbdreq_iois16= 2<<14,
- Cbdreq_spkr= 3<<14,
- Cboe= 1<<7,
- Cbreset= 1<<6,
-
- /* porN */
- Rport8= 0<<6,
- Rport16= 1<<6,
- Rmtype= 7<<3, /* memory type field */
- Rmem= 0<<3, /* common memory space */
- Rattrib= 2<<3, /* attribute space */
- Rio= 3<<3,
- Rdma= 4<<3, /* normal DMA */
- Rdmalx= 5<<3, /* DMA, last transaction */
- RA22_23= 6<<3, /* ``drive A22 and A23 signals on CE2 and CE1'' */
- RslotB= 1<<2, /* select slot B (always, on MPC823) */
- Rwp= 1<<1, /* write protect */
- Rvalid= 1<<0, /* region valid */
-
- Nmap= 8, /* max number of maps to use */
-
- /*
- * configuration registers - they start at an offset in attribute
- * memory found in the CIS.
- */
- Rconfig= 0,
- Creset= (1<<7), /* reset device */
- Clevel= (1<<6), /* level sensitive interrupt line */
- Rccsr= 2,
- Ciack = (1<<0),
- Cipend = (1<<1),
- Cpwrdown= (1<<2),
- Caudioen= (1<<3),
- Ciois8= (1<<5),
- Cchgena= (1<<6),
- Cchange= (1<<7),
- Rpin= 4, /* pin replacement register */
- Rscpr= 6, /* socket and copy register */
- Riob0= 10,
- Riob1= 12,
- Riob2= 14,
- Riob3= 16,
- Riolim= 18,
-
- Maxctab= 8, /* maximum configuration table entries */
- MaxCIS = 8192, /* maximum CIS size in bytes */
- Mgran = 8192, /* maximum size of reads and writes */
-
- Statusbounce=20, /* msec debounce time */
-};
-
-typedef struct Ctlr Ctlr;
-
-/* a controller (there's only one) */
-struct Ctlr
-{
- int dev;
- int nslot;
-
- /* memory maps */
- Lock mlock; /* lock down the maps */
- PCMmap mmap[Nmap]; /* maps */
-
- /* IO port allocation */
- ulong nextport;
-};
-static Ctlr controller[Maxctlr];
-
-static PCMslot *slot;
-static PCMslot *lastslot;
-static int nslot;
-
-static Map pcmmapv[Nmap+1];
-static RMap pcmmaps = {"PCMCIA mappings"};
-
-static void pcmciaintr(Ureg*, void*);
-static void pcmciareset(void);
-static int pcmio(int, ISAConf*);
-static long pcmread(int, int, void*, long, ulong);
-static long pcmwrite(int, int, void*, long, ulong);
-static void slotdis(PCMslot*);
-
-static ulong pcmmalloc(ulong, long);
-static void pcmfree(ulong, long);
-static void pcmciaproc(void*);
-
-static void pcmciadump(PCMslot*);
-
-/*
- * get info about card
- */
-static void
-slotinfo(PCMslot *pp)
-{
- ulong pipr;
-
- pipr = (m->iomem->pipr >> pp->slotshift) & 0xFF00;
-print("pipr=%8.8lux/%lux\n", m->iomem->pipr, pipr);
- pp->v3_3 = (pipr&Cbvs1)!=0;
- pp->voltage = (((pipr & Cbvs2)!=0)<<1) | ((pipr & Cbvs1)!=0);
- pp->occupied = (pipr&(Cbcd1|Cbcd2))==0;
- pp->powered = pcmpowered(pp->slotno);
- pp->battery = (pipr & (Cbbvd1|Cbbvd2))>>9;
- pp->wrprot = (pipr&Cbwp)!=0;
- pp->busy = (pipr&Cbrdy)==0;
-}
-
-static void
-pcmdelay(int ms)
-{
- if(up == nil)
- delay(ms);
- else
- tsleep(&up->sleep, return0, nil, ms);
-}
-
-/*
- * enable the slot card
- */
-static void
-slotena(PCMslot *pp)
-{
- IMM *io;
-
- if(pp->enabled)
- return;
- m->iomem->pgcr[pp->slotno] &= ~Cboe;
- pcmpower(pp->slotno, 1);
- eieio();
- pcmdelay(300);
- io = m->iomem;
- io->pgcr[pp->slotno] |= Cbreset; /* active high */
- eieio();
- pcmdelay(100);
- io->pgcr[pp->slotno] &= ~Cbreset;
- eieio();
- pcmdelay(500); /* ludicrous delay */
-
- /* get configuration */
- slotinfo(pp);
- if(pp->occupied){
- if(pp->cisread == 0){
- pcmcisread(pp);
- pp->cisread = 1;
- }
- pp->enabled = 1;
- } else{
- print("empty slot\n");
- slotdis(pp);
- }
-}
-
-/*
- * disable the slot card
- */
-static void
-slotdis(PCMslot *pp)
-{
- int i;
- Ctlr *ctlr;
- PCMmap *pm;
-
-iprint("slotdis %d\n", pp->slotno);
- pcmpower(pp->slotno, 0);
- m->iomem->pgcr[pp->slotno] |= Cboe;
- ctlr = pp->ctlr;
- for(i = 0; i < nelem(ctlr->mmap); i++){
- pm = &ctlr->mmap[i];
- if(m->iomem->pcmr[i].option & Rvalid && pm->slotno == pp->slotno)
- pcmunmap(pp->slotno, pm);
- }
- pp->enabled = 0;
- pp->cisread = 0;
-}
-
-static void
-pcmciardy(Ureg *ur, void *a)
-{
- PCMslot *pp;
- ulong w;
-
- pp = a;
- w = (m->iomem->pipr >> pp->slotshift) & 0xFF00;
- if(pp->occupied && (w & Cbrdy) == 0){ /* interrupt */
-print("PCM.%dI#%lux|", pp->slotno, w);
- if(pp->intr.f != nil)
- pp->intr.f(ur, pp->intr.arg);
- }
-}
-
-void
-pcmintrenable(int slotno, void (*f)(Ureg*, void*), void *arg)
-{
- PCMslot *pp;
- IMM *io;
- char name[KNAMELEN];
-
- if(slotno < 0 || slotno >= nslot)
- panic("pcmintrenable");
- snprint(name, sizeof(name), "pcmcia.irq%d", slotno);
- io = ioplock();
- pp = slot+slotno;
- pp->intr.f = f;
- pp->intr.arg = arg;
- intrenable(PCMCIAio, pcmciardy, pp, BUSUNKNOWN, name);
- io->per |= Cbrdy_l; /* assumes used for irq, not rdy; assumes level interrupt always right */
- iopunlock();
-}
-
-void
-pcmintrdisable(int slotno, void (*f)(Ureg*, void*), void *arg)
-{
- PCMslot *pp;
- IMM *io;
- char name[KNAMELEN];
-
- if(slotno < 0 || slotno >= nslot)
- panic("pcmintrdisable");
- snprint(name, sizeof(name), "pcmcia.irq%d", slotno);
- io = ioplock();
- pp = slot+slotno;
- if(pp->intr.f == f && pp->intr.arg == arg){
- pp->intr.f = nil;
- pp->intr.arg = nil;
- intrdisable(PCMCIAio, pcmciardy, pp, BUSUNKNOWN, name);
- io->per &= ~Cbrdy_l;
- }
- iopunlock();
-}
-
-/*
- * status change interrupt
- *
- * this wakes a monitoring process to read the CIS,
- * rather than holding other interrupts out here.
- */
-
-static Rendez pcmstate;
-
-static int
-statechanged(void *a)
-{
- PCMslot *pp;
- int in;
-
- pp = a;
- in = (m->iomem->pipr & (Cbcd1|Cbcd2))==0;
- return in != pp->occupied;
-}
-
-static void
-pcmciaintr(Ureg*, void*)
-{
- ulong events;
-
- if(slot == 0)
- return;
- events = m->iomem->pscr & (Cbvs1_c|Cbvs2_c|Cbwp_c|Cbcd2_c|Cbcd1_c|Cbbvd2_c|Cbbvd1_c);
- eieio();
- m->iomem->pscr = events;
- /* TO DO: other slot */
-iprint("PCM: #%lux|", events);
-iprint("pipr=#%lux|", m->iomem->pipr & 0xFF00);
- wakeup(&pcmstate);
-}
-
-static void
-pcmciaproc(void*)
-{
- ulong csc;
- PCMslot *pp;
- int was;
-
- for(;;){
- sleep(&pcmstate, statechanged, slot+1);
- tsleep(&up->sleep, return0, nil, Statusbounce);
- /*
- * voltage change 1,2
- * write protect change
- * card detect 1,2
- * battery voltage 1 change (or SPKR-bar)
- * battery voltage 2 change (or STSCHG-bar)
- * card B rdy / IRQ-bar low
- * card B rdy / IRQ-bar high
- * card B rdy / IRQ-bar rising edge
- * card B rdy / IRQ-bar falling edge
- *
- * TO DO: currently only handle card-present changes
- */
-
- for(pp = slot; pp < lastslot; pp++){
- if(pp->memlen == 0)
- continue;
- csc = (m->iomem->pipr>>pp->slotshift) & (Cbcd1|Cbcd2);
- was = pp->occupied;
- slotinfo(pp);
- if(csc == 0 && was != pp->occupied){
- if(!pp->occupied){
- slotdis(pp);
- if(pp->special && pp->notify.f != nil)
- pp->notify.f(pp->notify.arg, 1);
- }
- }
- }
- }
-}
-
-static uchar greycode[] = {
- 0, 1, 3, 2, 6, 7, 5, 4, 014, 015, 017, 016, 012, 013, 011, 010,
- 030, 031, 033, 032, 036, 037, 035, 034, 024, 025, 027
-};
-
-/*
- * get a map for pc card region, return corrected len
- */
-PCMmap*
-pcmmap(int slotno, ulong offset, int len, int attr)
-{
- Ctlr *ctlr;
- PCMslot *pp;
- PCMmap *pm, *nm;
- IMM *io;
- int i;
- ulong e, bsize, code, opt;
-
- if(0)
- print("pcmmap: %d #%lux %d #%x\n", slotno, offset, len, attr);
- pp = slot + slotno;
- if(!pp->occupied)
- return nil;
- if(attr == 1){ /* account for ../port/cis.c's conventions */
- attr = Rattrib;
- if(len <= 0)
- len = MaxCIS*2; /* TO DO */
- }
- ctlr = pp->ctlr;
-
- /* convert offset to granularity */
- if(len <= 0)
- len = 1;
- e = offset+len;
- for(i=0;; i++){
- if(i >= nelem(greycode))
- return nil;
- bsize = 1<<i;
- offset &= ~(bsize-1);
- if(e <= offset+bsize)
- break;
- }
- code = greycode[i];
- if(0)
- print("i=%d bsize=%lud code=0%luo\n", i, bsize, code);
- e = offset+bsize;
- len = bsize;
-
- lock(&ctlr->mlock);
-
- /* look for an existing map that covers the right area */
- io = m->iomem;
- nm = nil;
- for(i=0; i<Nmap; i++){
- pm = &ctlr->mmap[i];
- if(io->pcmr[i].option & Rvalid &&
- pm->slotno == slotno &&
- pm->attr == attr &&
- offset >= pm->ca && e <= pm->cea){
- pm->ref++;
- unlock(&ctlr->mlock);
- return pm;
- }
- if(nm == 0 && pm->ref == 0)
- nm = pm;
- }
- pm = nm;
- if(pm == nil){
- unlock(&ctlr->mlock);
- return nil;
- }
-
- /* set up new map */
- pm->isa = pcmmalloc(offset, len);
- if(pm->isa == 0){
- /* address not available: in use, or too much to map */
- unlock(&ctlr->mlock);
- return 0;
- }
- if(0)
- print("mx=%d isa=#%lux\n", (int)(pm - ctlr->mmap), pm->isa);
-
- pm->len = len;
- pm->ca = offset;
- pm->cea = pm->ca + pm->len;
- pm->attr = attr;
- i = pm - ctlr->mmap;
- io->pcmr[i].option &= ~Rvalid; /* disable map before changing it */
- io->pcmr[i].base = pm->isa;
- opt = attr;
- opt |= code<<27;
- if((attr&Rmtype) == Rio){
- opt |= 4<<12; /* PSST */
- opt |= 8<<7; /* PSL */
- opt |= 2<<16; /* PSHT */
- }else{
- opt |= 6<<12; /* PSST */
- opt |= 24<<7; /* PSL */
- opt |= 8<<16; /* PSHT */
- }
- if((attr & Rport16) == 0)
- opt |= Rport8;
- if(slotno == 1)
- opt |= RslotB;
- io->pcmr[i].option = opt | Rvalid;
- pm->slotno = slotno;
- pm->ref = 1;
-
- unlock(&ctlr->mlock);
- return pm;
-}
-
-static void
-pcmiomap(PCMslot *pp, PCMconftab *ct, int i)
-{
- int n, attr;
- Ctlr *ctlr;
-
- if(0)
- print("pcm iomap #%lux %lud\n", ct->io[i].start, ct->io[i].len);
- if(ct->io[i].len <= 0)
- return;
- if(ct->io[i].start == 0){
- n = 1<<ct->nlines;
- ctlr = pp->ctlr;
- lock(&ctlr->mlock);
- if(ctlr->nextport == 0)
- ctlr->nextport = 0xF000;
- ctlr->nextport = (ctlr->nextport + n - 1) & ~(n-1);
- ct->io[i].start = ctlr->nextport;
- ct->io[i].len = n;
- ctlr->nextport += n;
- unlock(&ctlr->mlock);
- }
- attr = Rio;
- if(ct->bit16)
- attr |= Rport16;
- ct->io[i].map = pcmmap(pp->slotno, ct->io[i].start, ct->io[i].len, attr);
-}
-
-void
-pcmunmap(int slotno, PCMmap* pm)
-{
- int i;
- PCMslot *pp;
- Ctlr *ctlr;
-
- pp = slot + slotno;
- if(pp->memlen == 0)
- return;
- ctlr = pp->ctlr;
- lock(&ctlr->mlock);
- if(pp->slotno == pm->slotno && --pm->ref == 0){
- i = pm - ctlr->mmap;
- m->iomem->pcmr[i].option = 0;
- m->iomem->pcmr[i].base = 0;
- pcmfree(pm->isa, pm->len);
- }
- unlock(&ctlr->mlock);
-}
-
-static void
-increfp(PCMslot *pp)
-{
- if(incref(pp) == 1)
- slotena(pp);
-}
-
-static void
-decrefp(PCMslot *pp)
-{
- if(decref(pp) == 0)
- slotdis(pp);
-}
-
-/*
- * look for a card whose version contains 'idstr'
- */
-int
-pcmspecial(char *idstr, ISAConf *isa)
-{
- PCMslot *pp;
- extern char *strstr(char*, char*);
-
- pcmciareset();
- for(pp = slot; pp < lastslot; pp++){
- if(pp->special || pp->memlen == 0)
- continue; /* already taken */
- increfp(pp);
- if(pp->occupied && strstr(pp->verstr, idstr)){
- print("PCMslot #%d: Found %s - ",pp->slotno, idstr);
- if(isa == 0 || pcmio(pp->slotno, isa) == 0){
- print("ok.\n");
- pp->special = 1;
- return pp->slotno;
- }
- print("error with isa io\n");
- }
- decrefp(pp);
- }
- return -1;
-}
-
-void
-pcmspecialclose(int slotno)
-{
- PCMslot *pp;
-
- if(slotno >= nslot)
- panic("pcmspecialclose");
- pp = slot + slotno;
- pp->special = 0;
- decrefp(pp);
-}
-
-void
-pcmnotify(int slotno, void (*f)(void*, int), void* a)
-{
- PCMslot *pp;
-
- if(slotno < 0 || slotno >= nslot)
- panic("pcmnotify");
- pp = slot + slotno;
- if(pp->occupied && pp->special){
- pp->notify.f = f;
- pp->notify.arg = a;
- }
-}
-
-/*
- * reserve pcmcia slot address space [addr, addr+size[,
- * returning a pointer to it, or nil if the space was already reserved.
- */
-static ulong
-pcmmalloc(ulong addr, long size)
-{
- return rmapalloc(&pcmmaps, PHYSPCMCIA+addr, size, size);
-}
-
-static void
-pcmfree(ulong a, long size)
-{
- if(a != 0 && size > 0)
- mapfree(&pcmmaps, a, size);
-}
-
-enum
-{
- Qdir,
- Qmem,
- Qattr,
- Qctl,
-};
-
-#define SLOTNO(c) ((c->qid.path>>8)&0xff)
-#define TYPE(c) (c->qid.path&0xff)
-#define QID(s,t) (((s)<<8)|(t))
-
-static int
-pcmgen(Chan *c, char*, Dirtab*, int, int i, Dir *dp)
-{
- int slotno;
- Qid qid;
- long len;
- PCMslot *pp;
-
- if(i>=3*nslot)
- return -1;
- slotno = i/3;
- pp = slot + slotno;
- if(pp->memlen == 0)
- return 0;
- len = 0;
- switch(i%3){
- case 0:
- qid.path = QID(slotno, Qmem);
- sprint(up->genbuf, "pcm%dmem", slotno);
- len = pp->memlen;
- break;
- case 1:
- qid.path = QID(slotno, Qattr);
- sprint(up->genbuf, "pcm%dattr", slotno);
- len = pp->memlen;
- break;
- case 2:
- qid.path = QID(slotno, Qctl);
- sprint(up->genbuf, "pcm%dctl", slotno);
- break;
- }
- qid.vers = 0;
- devdir(c, qid, up->genbuf, len, eve, 0660, dp);
- return 1;
-}
-
-/*
- * used only when debugging
- */
-static void
-pcmciadump(PCMslot *)
-{
- IMM *io;
- int i;
-
- io = m->iomem;
- print("pipr #%4.4lux pscr #%4.4lux per #%4.4lux pgcr[1] #%8.8lux\n",
- io->pipr & 0xFFFF, io->pscr & 0xFFFF, io->per & 0xFFFF, io->pgcr[1]);
- for(i=0; i<8; i++)
- print("pbr%d #%8.8lux por%d #%8.8lux\n", i, io->pcmr[i].base, i, io->pcmr[i].option);
-}
-
-/*
- * set up for slot cards
- */
-static void
-pcmciareset(void)
-{
- static int already;
- int i;
- Ctlr *cp;
- IMM *io;
- PCMslot *pp;
-
- if(already)
- return;
- already = 1;
-
- cp = controller;
- /* TO DO: set low power mode? ... */
-
- mapinit(&pcmmaps, pcmmapv, sizeof(pcmmapv));
- mapfree(&pcmmaps, PHYSPCMCIA, PCMCIALEN);
-
- io = m->iomem;
-
- for(i=0; i<8; i++){
- io->pcmr[i].option = 0;
- io->pcmr[i].base = 0;
- }
-
- io->pscr = ~0; /* reset status */
- /* TO DO: Cboe, Cbreset */
- /* TO DO: two slots except on 823 */
- pcmenable();
- /* TO DO: if the card is there turn on 5V power to keep its battery alive */
- slot = xalloc(Maxslot * sizeof(PCMslot));
- lastslot = slot;
- slot[0].slotshift = Slotashift;
- slot[1].slotshift = 0;
- for(i=0; i<Maxslot; i++){
- pp = &slot[i];
- if(!pcmslotavail(i)){
- pp->memlen = 0;
- continue;
- }
- io->per |= (Cbvs1_c|Cbvs2_c|Cbwp_c|Cbcd2_c|Cbcd1_c|Cbbvd2_c|Cbbvd1_c)<<pp->slotshift; /* enable status interrupts */
- io->pgcr[i] = (1<<(31-PCMCIAio)) | (1<<(23-PCMCIAstatus));
- pp->slotno = i;
- pp->memlen = 8*MB;
- pp->ctlr = cp;
- //slotdis(pp);
- lastslot = slot;
- nslot = i+1;
- }
- if(1)
- pcmciadump(slot);
- intrenable(PCMCIAstatus, pcmciaintr, cp, BUSUNKNOWN, "pcmcia");
- print("pcmcia reset\n");
-}
-
-static void
-pcmciainit(void)
-{
- kproc("pcmcia", pcmciaproc, nil, 0);
-}
-
-static Chan*
-pcmciaattach(char *spec)
-{
- return devattach('y', spec);
-}
-
-static Walkqid*
-pcmciawalk(Chan *c, Chan *nc, char **name, int nname)
-{
- return devwalk(c, nc, name, nname, 0, 0, pcmgen);
-}
-
-static int
-pcmciastat(Chan *c, uchar *dp, int n)
-{
- return devstat(c, dp, n, 0, 0, pcmgen);
-}
-
-static Chan*
-pcmciaopen(Chan *c, int omode)
-{
- if(c->qid.type & QTDIR){
- if(omode != OREAD)
- error(Eperm);
- } else
- increfp(slot + SLOTNO(c));
- c->mode = openmode(omode);
- c->flag |= COPEN;
- c->offset = 0;
- return c;
-}
-
-static void
-pcmciaclose(Chan *c)
-{
- if(c->flag & COPEN)
- if((c->qid.type & QTDIR) == 0)
- decrefp(slot+SLOTNO(c));
-}
-
-/* a memmove using only bytes */
-static void
-memmoveb(uchar *to, uchar *from, int n)
-{
- while(n-- > 0)
- *to++ = *from++;
-}
-
-static long
-pcmread(int slotno, int attr, void *a, long n, ulong offset)
-{
- int i, len;
- PCMmap *m;
- void *ka;
- uchar *ac;
- PCMslot *pp;
-
- pp = slot + slotno;
- if(pp->memlen < offset)
- return 0;
- if(pp->memlen < offset + n)
- n = pp->memlen - offset;
-
- ac = a;
- for(len = n; len > 0; len -= i){
- if((i = len) > Mgran)
- i = Mgran;
- m = pcmmap(pp->slotno, offset, i, attr? Rattrib: Rmem);
- if(m == 0)
- error("can't map PCMCIA card");
- if(waserror()){
- if(m)
- pcmunmap(pp->slotno, m);
- nexterror();
- }
- if(offset + len > m->cea)
- i = m->cea - offset;
- else
- i = len;
- ka = (char*)KADDR(m->isa) + (offset - m->ca);
- memmoveb(ac, ka, i);
- poperror();
- pcmunmap(pp->slotno, m);
- offset += i;
- ac += i;
- }
-
- return n;
-}
-
-static long
-pcmciaread(Chan *c, void *a, long n, vlong offset)
-{
- char *cp, *buf;
- ulong p;
- PCMslot *pp;
-
- p = TYPE(c);
- switch(p){
- case Qdir:
- return devdirread(c, a, n, 0, 0, pcmgen);
- case Qmem:
- case Qattr:
- return pcmread(SLOTNO(c), p==Qattr, a, n, offset);
- case Qctl:
- buf = malloc(READSTR);
- if(buf == nil)
- error(Enomem);
- if(waserror()){
- free(buf);
- nexterror();
- }
- cp = buf;
- pp = slot + SLOTNO(c);
- if(pp->occupied)
- cp += sprint(cp, "occupied\n");
- if(pp->enabled)
- cp += sprint(cp, "enabled\n");
- if(pp->powered)
- cp += sprint(cp, "powered\n");
- if(pp->configed)
- cp += sprint(cp, "configed\n");
- if(pp->wrprot)
- cp += sprint(cp, "write protected\n");
- if(pp->busy)
- cp += sprint(cp, "busy\n");
- if(pp->v3_3)
- cp += sprint(cp, "3.3v ok\n");
- cp += sprint(cp, "battery lvl %d\n", pp->battery);
- cp += sprint(cp, "voltage select %d\n", pp->voltage);
- /* TO DO: could return pgcr[] values for debugging */
- *cp = 0;
- n = readstr(offset, a, n, buf);
- poperror();
- free(buf);
- break;
- default:
- n=0;
- break;
- }
- return n;
-}
-
-static long
-pcmwrite(int dev, int attr, void *a, long n, ulong offset)
-{
- int i, len;
- PCMmap *m;
- void *ka;
- uchar *ac;
- PCMslot *pp;
-
- pp = slot + dev;
- if(pp->memlen < offset)
- return 0;
- if(pp->memlen < offset + n)
- n = pp->memlen - offset;
-
- ac = a;
- for(len = n; len > 0; len -= i){
- if((i = len) > Mgran)
- i = Mgran;
- m = pcmmap(pp->slotno, offset, i, attr? Rattrib: Rmem);
- if(m == 0)
- error("can't map PCMCIA card");
- if(waserror()){
- if(m)
- pcmunmap(pp->slotno, m);
- nexterror();
- }
- if(offset + len > m->cea)
- i = m->cea - offset;
- else
- i = len;
- ka = (char*)KADDR(m->isa) + (offset - m->ca);
- memmoveb(ka, ac, i);
- poperror();
- pcmunmap(pp->slotno, m);
- offset += i;
- ac += i;
- }
-
- return n;
-}
-
-static long
-pcmciawrite(Chan *c, void *a, long n, vlong offset)
-{
- ulong p;
- PCMslot *pp;
- char buf[32];
-
- p = TYPE(c);
- switch(p){
- case Qctl:
- if(n >= sizeof(buf))
- n = sizeof(buf) - 1;
- strncpy(buf, a, n);
- buf[n] = 0;
- pp = slot + SLOTNO(c);
- if(!pp->occupied)
- error(Eio);
-
- /* set vpp on card */
- if(strncmp(buf, "vpp", 3) == 0){
- p = strtol(buf+3, nil, 0);
- pcmsetvpp(pp->slotno, p);
- }
- break;
- case Qmem:
- case Qattr:
- pp = slot + SLOTNO(c);
- if(pp->occupied == 0 || pp->enabled == 0)
- error(Eio);
- n = pcmwrite(pp->slotno, p == Qattr, a, n, offset);
- if(n < 0)
- error(Eio);
- break;
- default:
- error(Ebadusefd);
- }
- return n;
-}
-
-Dev pcmciadevtab = {
- 'y',
- "pcmcia",
-
- pcmciareset,
- pcmciainit,
- devshutdown,
- pcmciaattach,
- pcmciawalk,
- pcmciastat,
- pcmciaopen,
- devcreate,
- pcmciaclose,
- pcmciaread,
- devbread,
- pcmciawrite,
- devbwrite,
- devremove,
- devwstat,
-};
-
-/*
- * configure the PCMslot for IO. We assume very heavily that we can read
- * configuration info from the CIS. If not, we won't set up correctly.
- */
-static int
-pcmio(int slotno, ISAConf *isa)
-{
- PCMslot *pp;
- PCMconftab *ct, *et, *t;
- PCMmap *pm;
- uchar *p;
- int irq, i, x;
-
- irq = isa->irq;
- if(irq == 2)
- irq = 9;
-
- if(slotno > nslot)
- return -1;
- pp = slot + slotno;
-
- if(!pp->occupied)
- return -1;
-
- et = &pp->ctab[pp->nctab];
-
- /* assume default is right */
- if(pp->def)
- ct = pp->def;
- else
- ct = pp->ctab;
- /* try for best match */
- if(ct->nlines == 0 || ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
- for(t = pp->ctab; t < et; t++)
- if(t->nlines && t->io[0].start == isa->port && ((1<<irq) & t->irqs)){
- ct = t;
- break;
- }
- }
- if(ct->nlines == 0 || ((1<<irq) & ct->irqs) == 0){
- for(t = pp->ctab; t < et; t++)
- if(t->nlines && ((1<<irq) & t->irqs)){
- ct = t;
- break;
- }
- }
- if(ct->nlines == 0){
- for(t = pp->ctab; t < et; t++)
- if(t->nlines){
- ct = t;
- break;
- }
- }
-print("slot %d: nlines=%d iolen=%lud irq=%d ct->index=%d nport=%d ct->port=#%lux/%lux\n", slotno, ct->nlines, ct->io[0].len, irq, ct->index, ct->nio, ct->io[0].start, isa->port);
- if(ct == et || ct->nlines == 0)
- return -1;
- /* route interrupts */
- isa->irq = irq;
- //wrreg(pp, Rigc, irq | Fnotreset | Fiocard);
- delay(2);
-
- /* set power and enable device */
- pcmsetvcc(pp->slotno, ct->vcc);
- pcmsetvpp(pp->slotno, ct->vpp1);
-
- delay(2); /* could poll BSY during power change */
-
- for(i=0; i<ct->nio; i++)
- pcmiomap(pp, ct, i);
-
- if(ct->nio)
- isa->port = ct->io[0].start;
-
- /* only touch Rconfig if it is present */
- if(pp->cpresent & (1<<Rconfig)){
-print("Rconfig present: #%lux\n", pp->caddr+Rconfig);
- /* Reset adapter */
- pm = pcmmap(slotno, pp->caddr + Rconfig, 1, Rattrib);
- if(pm == nil)
- return -1;
-
- p = (uchar*)KADDR(pm->isa) + (pp->caddr + Rconfig - pm->ca);
-
- /* set configuration and interrupt type */
- x = ct->index;
- if((ct->irqtype & 0x20) && ((ct->irqtype & 0x40)==0 || isa->irq>7))
- x |= Clevel;
- *p = x;
- delay(5);
-
- pcmunmap(pp->slotno, pm);
-print("Adapter reset\n");
- }
-
- return 0;
-}