/* cardbus and pcmcia (grmph) support.*/#include "u.h"#include "lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "error.h"#include "io.h" #define ioalloc(addr, len, align, name) (addr)#define iofree(addr)extern int pciscan(int, Pcidev **);extern ulong pcibarsize(Pcidev *, int); int (*_pcmspecial)(char *, ISAConf *);void (*_pcmspecialclose)(int); intpcmspecial(char *idstr, ISAConf *isa){ return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1;} voidpcmspecialclose(int a){ if (_pcmspecialclose != nil) _pcmspecialclose(a);} static ulongioreserve(ulong, int size, int align, char *){ static ulong isaend = 0xfd00; ulong ioaddr; if (align) isaend = ((isaend + align - 1) / align) * align; ioaddr = isaend; isaend += size; return ioaddr;} #define MAP(x,o) (Rmap + (x)*0x8 + o) enum { TI_vid = 0x104c, TI_1131_did = 0xAC15, TI_1250_did = 0xAC16, TI_1450_did = 0xAC1B, TI_1251A_did = 0xAC1D, Ricoh_vid = 0x1180, Ricoh_476_did = 0x0476, Ricoh_478_did = 0x0478, Nslots = 4, /* Maximum number of CardBus slots to use */ K = 1024, M = K * K, LegacyAddr = 0x3e0, NUMEVENTS = 10, TI1131xSC = 0x80, // system control TI122X_SC_INTRTIE = 1 << 29, TI12xxIM = 0x8c, // TI1131xCC = 0x91, // card control TI113X_CC_RIENB = 1 << 7, TI113X_CC_ZVENABLE = 1 << 6, TI113X_CC_PCI_IRQ_ENA = 1 << 5, TI113X_CC_PCI_IREQ = 1 << 4, TI113X_CC_PCI_CSC = 1 << 3, TI113X_CC_SPKROUTEN = 1 << 1, TI113X_CC_IFG = 1 << 0, TI1131xDC = 0x92, // device control}; typedef struct { ushort r_vid; ushort r_did; char *r_name;} variant_t; static variant_t variant[] = {{ Ricoh_vid, Ricoh_476_did, "Ricoh 476 PCI/Cardbus bridge", },{ Ricoh_vid, Ricoh_478_did, "Ricoh 478 PCI/Cardbus bridge", },{ TI_vid, TI_1131_did, "TI PCI-1131 Cardbus Controller", },{ TI_vid, TI_1250_did, "TI PCI-1250 Cardbus Controller", },{ TI_vid, TI_1450_did, "TI PCI-1450 Cardbus Controller", },{ TI_vid, TI_1251A_did, "TI PCI-1251A Cardbus Controller", },}; /* Cardbus registers */enum { SocketEvent = 0, SE_CCD = 3 << 1, SE_POWER = 1 << 3, SocketMask = 1, SocketState = 2, SS_CCD = 3 << 1, SS_POWER = 1 << 3, SS_PC16 = 1 << 4, SS_CBC = 1 << 5, SS_NOTCARD = 1 << 7, SS_BADVCC = 1 << 9, SS_5V = 1 << 10, SS_3V = 1 << 11, SocketForce = 3, SocketControl = 4, SC_5V = 0x22, SC_3V = 0x33,}; enum { PciPCR_IO = 1 << 0, PciPCR_MEM = 1 << 1, PciPCR_Master = 1 << 2, Nbars = 6, Ncmd = 10, CBIRQ = 9, PC16, PC32,}; enum { Ti82365, Tpd6710, Tpd6720, Tvg46x,}; static char *chipname[] = {[Ti82365] "Intel 82365SL",[Tpd6710] "Cirrus Logic PD6710",[Tpd6720] "Cirrus Logic PD6720",[Tvg46x] "Vadem VG-46x",}; /* * Intel 82365SL PCIC controller for the PCMCIA or * Cirrus Logic PD6710/PD6720 which is mostly register compatible */enum{ /* * registers indices */ Rid= 0x0, /* identification and revision */ Ris= 0x1, /* interface status */ Rpc= 0x2, /* power control */ Foutena= (1<<7), /* output enable */ Fautopower= (1<<5), /* automatic power switching */ Fcardena= (1<<4), /* PC card enable */ Rigc= 0x3, /* interrupt and general control */ Fiocard= (1<<5), /* I/O card (vs memory) */ Fnotreset= (1<<6), /* reset if not set */ FSMIena= (1<<4), /* enable change interrupt on SMI */ Rcsc= 0x4, /* card status change */ Rcscic= 0x5, /* card status change interrupt config */ Fchangeena= (1<<3), /* card changed */ Fbwarnena= (1<<1), /* card battery warning */ Fbdeadena= (1<<0), /* card battery dead */ Rwe= 0x6, /* address window enable */ Fmem16= (1<<5), /* use A23-A12 to decode address */ Rio= 0x7, /* I/O control */ Fwidth16= (1<<0), /* 16 bit data width */ Fiocs16= (1<<1), /* IOCS16 determines data width */ Fzerows= (1<<2), /* zero wait state */ Ftiming= (1<<3), /* timing register to use */ Riobtm0lo= 0x8, /* I/O address 0 start low byte */ Riobtm0hi= 0x9, /* I/O address 0 start high byte */ Riotop0lo= 0xa, /* I/O address 0 stop low byte */ Riotop0hi= 0xb, /* I/O address 0 stop high byte */ Riobtm1lo= 0xc, /* I/O address 1 start low byte */ Riobtm1hi= 0xd, /* I/O address 1 start high byte */ Riotop1lo= 0xe, /* I/O address 1 stop low byte */ Riotop1hi= 0xf, /* I/O address 1 stop high byte */ Rmap= 0x10, /* map 0 */ /* * CL-PD67xx extension registers */ Rmisc1= 0x16, /* misc control 1 */ F5Vdetect= (1<<0), Fvcc3V= (1<<1), Fpmint= (1<<2), Fpsirq= (1<<3), Fspeaker= (1<<4), Finpack= (1<<7), Rfifo= 0x17, /* fifo control */ Fflush= (1<<7), /* flush fifo */ Rmisc2= 0x1E, /* misc control 2 */ Flowpow= (1<<1), /* low power mode */ Rchipinfo= 0x1F, /* chip information */ Ratactl= 0x26, /* ATA control */ /* * offsets into the system memory address maps */ Mbtmlo= 0x0, /* System mem addr mapping start low byte */ Mbtmhi= 0x1, /* System mem addr mapping start high byte */ F16bit= (1<<7), /* 16-bit wide data path */ Mtoplo= 0x2, /* System mem addr mapping stop low byte */ Mtophi= 0x3, /* System mem addr mapping stop high byte */ Ftimer1= (1<<6), /* timer set 1 */ Mofflo= 0x4, /* Card memory offset address low byte */ Moffhi= 0x5, /* Card memory offset address high byte */ Fregactive= (1<<6), /* attribute memory */ /* * 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 */}; /* * read and crack the card information structure enough to set * important parameters like power *//* cis memory walking */typedef struct Cisdat { uchar *cisbase; int cispos; int cisskip; int cislen;} Cisdat; /* configuration table entry */typedef struct PCMconftab PCMconftab;struct PCMconftab{ int index; ushort irqs; /* legal irqs */ uchar irqtype; uchar bit16; /* true for 16 bit access */ struct { ulong start; ulong len; } io[16]; int nio; uchar vpp1; uchar vpp2; uchar memwait; ulong maxwait; ulong readywait; ulong otherwait;}; typedef struct { char pi_verstr[512]; /* Version string */ PCMmap pi_mmap[4]; /* maps, last is always for the kernel */ ulong pi_conf_addr; /* Config address */ uchar pi_conf_present; /* Config register present */ int pi_nctab; /* In use configuration tables */ PCMconftab pi_ctab[8]; /* Configuration tables */ PCMconftab *pi_defctab; /* Default conftab */ int pi_port; /* Actual port usage */ int pi_irq; /* Actual IRQ usage */} pcminfo_t; #define qlock(i) {/* nothing to do */;}#define qunlock(i) {/* nothing to do */;}typedef struct QLock { int r; } QLock; typedef struct { QLock; variant_t *cb_variant; /* Which CardBus chipset */ Pcidev *cb_pci; /* The bridge itself */ ulong *cb_regs; /* Cardbus registers */ int cb_ltype; /* Legacy type */ int cb_lindex; /* Legacy port index address */ int cb_ldata; /* Legacy port data address */ int cb_lbase; /* Base register for this socket */ int cb_state; /* Current state of card */ int cb_type; /* Type of card */ pcminfo_t cb_linfo; /* PCMCIA slot info */ int cb_refs; /* Number of refs to slot */ QLock cb_refslock; /* inc/dev ref lock */} cb_t; static int managerstarted; enum { Mshift= 12, Mgran= (1<<Mshift), /* granularity of maps */ Mmask= ~(Mgran-1), /* mask for address bits important to the chip */}; static cb_t cbslots[Nslots];static int nslots; static ulong exponent[8] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, }; static ulong vmant[16] = { 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,}; static ulong mantissa[16] = { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, }; static char Enocard[] = "No card in slot"; static void cbint(Ureg *, void *);static int powerup(cb_t *);static void configure(cb_t *);static void managecard(cb_t *);static void cardmanager(void *);static void eject(cb_t *);static void interrupt(Ureg *, void *);static void powerdown(cb_t *cb);static void unconfigure(cb_t *cb); static void i82365probe(cb_t *cb, int lindex, int ldata);static void i82365configure(cb_t *cb);static PCMmap *isamap(cb_t *cb, ulong offset, int len, int attr);static void isaunmap(PCMmap* m);static uchar rdreg(cb_t *cb, int index);static void wrreg(cb_t *cb, int index, uchar val);static int readc(Cisdat *cis, uchar *x);static void tvers1(cb_t *cb, Cisdat *cis, int );static void tcfig(cb_t *cb, Cisdat *cis, int );static void tentry(cb_t *cb, Cisdat *cis, int );static int vcode(int volt);static int pccard_pcmspecial(char *idstr, ISAConf *isa);static void pccard_pcmspecialclose(int slotno); enum { CardDetected, CardPowered, CardEjected, CardConfigured,}; static char *messages[] = {[CardDetected] "CardDetected",[CardPowered] "CardPowered",[CardEjected] "CardEjected",[CardConfigured] "CardConfigured",}; enum { SlotEmpty, SlotFull, SlotPowered, SlotConfigured,}; static char *states[] = {[SlotEmpty] "SlotEmpty",[SlotFull] "SlotFull",[SlotPowered] "SlotPowered",[SlotConfigured] "SlotConfigured",}; static voidengine(cb_t *cb, int message){ // print("engine(%d): %s(%s)\n", // (int)(cb - cbslots), states[cb->cb_state], messages[message]); switch (cb->cb_state) { case SlotEmpty: switch (message) { case CardDetected: cb->cb_state = SlotFull; powerup(cb); break; case CardEjected: break; default: print("#Y%d: Invalid message %s in SlotEmpty state\n", (int)(cb - cbslots), messages[message]); break; } break; case SlotFull: switch (message) { case CardPowered: cb->cb_state = SlotPowered; configure(cb); break; case CardEjected: cb->cb_state = SlotEmpty; powerdown(cb); break; default: //print("#Y%d: Invalid message %s in SlotFull state\n", // (int)(cb - cbslots), messages[message]); break; } break; case SlotPowered: switch (message) { case CardConfigured: cb->cb_state = SlotConfigured; break; case CardEjected: cb->cb_state = SlotEmpty; unconfigure(cb); powerdown(cb); break; default: print("#Y%d: Invalid message %s in SlotPowered state\n", (int)(cb - cbslots), messages[message]); break; } break; case SlotConfigured: switch (message) { case CardEjected: cb->cb_state = SlotEmpty; unconfigure(cb); powerdown(cb); break; default: print("#Y%d: Invalid message %s in SlotConfigured state\n", (int)(cb - cbslots), messages[message]); break; } break; }} static voidqengine(cb_t *cb, int message){ qlock(cb); engine(cb, message); qunlock(cb);} typedef struct { cb_t *e_cb; int e_message;} events_t; static Lock levents;static events_t events[NUMEVENTS];// static Rendez revents;static int nevents; //static void//iengine(cb_t *cb, int message)//{// if (nevents >= NUMEVENTS) {// print("#Y: Too many events queued, discarding request\n");// return;// }// ilock(&levents);// events[nevents].e_cb = cb;// events[nevents].e_message = message;// nevents++;// iunlock(&levents);// wakeup(&revents);//} static inteventoccured(void){ return nevents > 0;} // static void// processevents(void *)// {// while (1) {// int message;// cb_t *cb;//// sleep(&revents, (int (*)(void *))eventoccured, nil);//// cb = nil;// message = 0;// ilock(&levents);// if (nevents > 0) {// cb = events[0].e_cb;// message = events[0].e_message;// nevents--;// if (nevents > 0)// memmove(events, &events[1], nevents * sizeof(events_t));Lines 1–500 of 1957. Load more
/* cardbus and pcmcia (grmph) support. */ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "error.h" #include "io.h" #define ioalloc(addr, len, align, name) (addr) #define iofree(addr) extern int pciscan(int, Pcidev **); extern ulong pcibarsize(Pcidev *, int); int (*_pcmspecial)(char *, ISAConf *); void (*_pcmspecialclose)(int); int pcmspecial(char *idstr, ISAConf *isa) { return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1; } void pcmspecialclose(int a) { if (_pcmspecialclose != nil) _pcmspecialclose(a); } static ulong ioreserve(ulong, int size, int align, char *) { static ulong isaend = 0xfd00; ulong ioaddr; if (align) isaend = ((isaend + align - 1) / align) * align; ioaddr = isaend; isaend += size; return ioaddr; } #define MAP(x,o) (Rmap + (x)*0x8 + o) enum { TI_vid = 0x104c, TI_1131_did = 0xAC15, TI_1250_did = 0xAC16, TI_1450_did = 0xAC1B, TI_1251A_did = 0xAC1D, Ricoh_vid = 0x1180, Ricoh_476_did = 0x0476, Ricoh_478_did = 0x0478, Nslots = 4, /* Maximum number of CardBus slots to use */ K = 1024, M = K * K, LegacyAddr = 0x3e0, NUMEVENTS = 10, TI1131xSC = 0x80, // system control TI122X_SC_INTRTIE = 1 << 29, TI12xxIM = 0x8c, // TI1131xCC = 0x91, // card control TI113X_CC_RIENB = 1 << 7, TI113X_CC_ZVENABLE = 1 << 6, TI113X_CC_PCI_IRQ_ENA = 1 << 5, TI113X_CC_PCI_IREQ = 1 << 4, TI113X_CC_PCI_CSC = 1 << 3, TI113X_CC_SPKROUTEN = 1 << 1, TI113X_CC_IFG = 1 << 0, TI1131xDC = 0x92, // device control }; typedef struct { ushort r_vid; ushort r_did; char *r_name; } variant_t; static variant_t variant[] = { { Ricoh_vid, Ricoh_476_did, "Ricoh 476 PCI/Cardbus bridge", }, { Ricoh_vid, Ricoh_478_did, "Ricoh 478 PCI/Cardbus bridge", }, { TI_vid, TI_1131_did, "TI PCI-1131 Cardbus Controller", }, { TI_vid, TI_1250_did, "TI PCI-1250 Cardbus Controller", }, { TI_vid, TI_1450_did, "TI PCI-1450 Cardbus Controller", }, { TI_vid, TI_1251A_did, "TI PCI-1251A Cardbus Controller", }, }; /* Cardbus registers */ enum { SocketEvent = 0, SE_CCD = 3 << 1, SE_POWER = 1 << 3, SocketMask = 1, SocketState = 2, SS_CCD = 3 << 1, SS_POWER = 1 << 3, SS_PC16 = 1 << 4, SS_CBC = 1 << 5, SS_NOTCARD = 1 << 7, SS_BADVCC = 1 << 9, SS_5V = 1 << 10, SS_3V = 1 << 11, SocketForce = 3, SocketControl = 4, SC_5V = 0x22, SC_3V = 0x33, }; enum { PciPCR_IO = 1 << 0, PciPCR_MEM = 1 << 1, PciPCR_Master = 1 << 2, Nbars = 6, Ncmd = 10, CBIRQ = 9, PC16, PC32, }; enum { Ti82365, Tpd6710, Tpd6720, Tvg46x, }; static char *chipname[] = { [Ti82365] "Intel 82365SL", [Tpd6710] "Cirrus Logic PD6710", [Tpd6720] "Cirrus Logic PD6720", [Tvg46x] "Vadem VG-46x", }; /* * Intel 82365SL PCIC controller for the PCMCIA or * Cirrus Logic PD6710/PD6720 which is mostly register compatible */ enum { /* * registers indices */ Rid= 0x0, /* identification and revision */ Ris= 0x1, /* interface status */ Rpc= 0x2, /* power control */ Foutena= (1<<7), /* output enable */ Fautopower= (1<<5), /* automatic power switching */ Fcardena= (1<<4), /* PC card enable */ Rigc= 0x3, /* interrupt and general control */ Fiocard= (1<<5), /* I/O card (vs memory) */ Fnotreset= (1<<6), /* reset if not set */ FSMIena= (1<<4), /* enable change interrupt on SMI */ Rcsc= 0x4, /* card status change */ Rcscic= 0x5, /* card status change interrupt config */ Fchangeena= (1<<3), /* card changed */ Fbwarnena= (1<<1), /* card battery warning */ Fbdeadena= (1<<0), /* card battery dead */ Rwe= 0x6, /* address window enable */ Fmem16= (1<<5), /* use A23-A12 to decode address */ Rio= 0x7, /* I/O control */ Fwidth16= (1<<0), /* 16 bit data width */ Fiocs16= (1<<1), /* IOCS16 determines data width */ Fzerows= (1<<2), /* zero wait state */ Ftiming= (1<<3), /* timing register to use */ Riobtm0lo= 0x8, /* I/O address 0 start low byte */ Riobtm0hi= 0x9, /* I/O address 0 start high byte */ Riotop0lo= 0xa, /* I/O address 0 stop low byte */ Riotop0hi= 0xb, /* I/O address 0 stop high byte */ Riobtm1lo= 0xc, /* I/O address 1 start low byte */ Riobtm1hi= 0xd, /* I/O address 1 start high byte */ Riotop1lo= 0xe, /* I/O address 1 stop low byte */ Riotop1hi= 0xf, /* I/O address 1 stop high byte */ Rmap= 0x10, /* map 0 */ /* * CL-PD67xx extension registers */ Rmisc1= 0x16, /* misc control 1 */ F5Vdetect= (1<<0), Fvcc3V= (1<<1), Fpmint= (1<<2), Fpsirq= (1<<3), Fspeaker= (1<<4), Finpack= (1<<7), Rfifo= 0x17, /* fifo control */ Fflush= (1<<7), /* flush fifo */ Rmisc2= 0x1E, /* misc control 2 */ Flowpow= (1<<1), /* low power mode */ Rchipinfo= 0x1F, /* chip information */ Ratactl= 0x26, /* ATA control */ /* * offsets into the system memory address maps */ Mbtmlo= 0x0, /* System mem addr mapping start low byte */ Mbtmhi= 0x1, /* System mem addr mapping start high byte */ F16bit= (1<<7), /* 16-bit wide data path */ Mtoplo= 0x2, /* System mem addr mapping stop low byte */ Mtophi= 0x3, /* System mem addr mapping stop high byte */ Ftimer1= (1<<6), /* timer set 1 */ Mofflo= 0x4, /* Card memory offset address low byte */ Moffhi= 0x5, /* Card memory offset address high byte */ Fregactive= (1<<6), /* attribute memory */ /* * 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 */ }; /* * read and crack the card information structure enough to set * important parameters like power */ /* cis memory walking */ typedef struct Cisdat { uchar *cisbase; int cispos; int cisskip; int cislen; } Cisdat; /* configuration table entry */ typedef struct PCMconftab PCMconftab; struct PCMconftab { int index; ushort irqs; /* legal irqs */ uchar irqtype; uchar bit16; /* true for 16 bit access */ struct { ulong start; ulong len; } io[16]; int nio; uchar vpp1; uchar vpp2; uchar memwait; ulong maxwait; ulong readywait; ulong otherwait; }; typedef struct { char pi_verstr[512]; /* Version string */ PCMmap pi_mmap[4]; /* maps, last is always for the kernel */ ulong pi_conf_addr; /* Config address */ uchar pi_conf_present; /* Config register present */ int pi_nctab; /* In use configuration tables */ PCMconftab pi_ctab[8]; /* Configuration tables */ PCMconftab *pi_defctab; /* Default conftab */ int pi_port; /* Actual port usage */ int pi_irq; /* Actual IRQ usage */ } pcminfo_t; #define qlock(i) {/* nothing to do */;} #define qunlock(i) {/* nothing to do */;} typedef struct QLock { int r; } QLock; typedef struct { QLock; variant_t *cb_variant; /* Which CardBus chipset */ Pcidev *cb_pci; /* The bridge itself */ ulong *cb_regs; /* Cardbus registers */ int cb_ltype; /* Legacy type */ int cb_lindex; /* Legacy port index address */ int cb_ldata; /* Legacy port data address */ int cb_lbase; /* Base register for this socket */ int cb_state; /* Current state of card */ int cb_type; /* Type of card */ pcminfo_t cb_linfo; /* PCMCIA slot info */ int cb_refs; /* Number of refs to slot */ QLock cb_refslock; /* inc/dev ref lock */ } cb_t; static int managerstarted; enum { Mshift= 12, Mgran= (1<<Mshift), /* granularity of maps */ Mmask= ~(Mgran-1), /* mask for address bits important to the chip */ }; static cb_t cbslots[Nslots]; static int nslots; static ulong exponent[8] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, }; static ulong vmant[16] = { 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90, }; static ulong mantissa[16] = { 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, }; static char Enocard[] = "No card in slot"; static void cbint(Ureg *, void *); static int powerup(cb_t *); static void configure(cb_t *); static void managecard(cb_t *); static void cardmanager(void *); static void eject(cb_t *); static void interrupt(Ureg *, void *); static void powerdown(cb_t *cb); static void unconfigure(cb_t *cb); static void i82365probe(cb_t *cb, int lindex, int ldata); static void i82365configure(cb_t *cb); static PCMmap *isamap(cb_t *cb, ulong offset, int len, int attr); static void isaunmap(PCMmap* m); static uchar rdreg(cb_t *cb, int index); static void wrreg(cb_t *cb, int index, uchar val); static int readc(Cisdat *cis, uchar *x); static void tvers1(cb_t *cb, Cisdat *cis, int ); static void tcfig(cb_t *cb, Cisdat *cis, int ); static void tentry(cb_t *cb, Cisdat *cis, int ); static int vcode(int volt); static int pccard_pcmspecial(char *idstr, ISAConf *isa); static void pccard_pcmspecialclose(int slotno); enum { CardDetected, CardPowered, CardEjected, CardConfigured, }; static char *messages[] = { [CardDetected] "CardDetected", [CardPowered] "CardPowered", [CardEjected] "CardEjected", [CardConfigured] "CardConfigured", }; enum { SlotEmpty, SlotFull, SlotPowered, SlotConfigured, }; static char *states[] = { [SlotEmpty] "SlotEmpty", [SlotFull] "SlotFull", [SlotPowered] "SlotPowered", [SlotConfigured] "SlotConfigured", }; static void engine(cb_t *cb, int message) { // print("engine(%d): %s(%s)\n", // (int)(cb - cbslots), states[cb->cb_state], messages[message]); switch (cb->cb_state) { case SlotEmpty: switch (message) { case CardDetected: cb->cb_state = SlotFull; powerup(cb); break; case CardEjected: break; default: print("#Y%d: Invalid message %s in SlotEmpty state\n", (int)(cb - cbslots), messages[message]); break; } break; case SlotFull: switch (message) { case CardPowered: cb->cb_state = SlotPowered; configure(cb); break; case CardEjected: cb->cb_state = SlotEmpty; powerdown(cb); break; default: //print("#Y%d: Invalid message %s in SlotFull state\n", // (int)(cb - cbslots), messages[message]); break; } break; case SlotPowered: switch (message) { case CardConfigured: cb->cb_state = SlotConfigured; break; case CardEjected: cb->cb_state = SlotEmpty; unconfigure(cb); powerdown(cb); break; default: print("#Y%d: Invalid message %s in SlotPowered state\n", (int)(cb - cbslots), messages[message]); break; } break; case SlotConfigured: switch (message) { case CardEjected: cb->cb_state = SlotEmpty; unconfigure(cb); powerdown(cb); break; default: print("#Y%d: Invalid message %s in SlotConfigured state\n", (int)(cb - cbslots), messages[message]); break; } break; } } static void qengine(cb_t *cb, int message) { qlock(cb); engine(cb, message); qunlock(cb); } typedef struct { cb_t *e_cb; int e_message; } events_t; static Lock levents; static events_t events[NUMEVENTS]; // static Rendez revents; static int nevents; //static void //iengine(cb_t *cb, int message) //{ // if (nevents >= NUMEVENTS) { // print("#Y: Too many events queued, discarding request\n"); // return; // } // ilock(&levents); // events[nevents].e_cb = cb; // events[nevents].e_message = message; // nevents++; // iunlock(&levents); // wakeup(&revents); //} static int eventoccured(void) { return nevents > 0; } // static void // processevents(void *) // { // while (1) { // int message; // cb_t *cb; // // sleep(&revents, (int (*)(void *))eventoccured, nil); // // cb = nil; // message = 0; // ilock(&levents); // if (nevents > 0) { // cb = events[0].e_cb; // message = events[0].e_message; // nevents--; // if (nevents > 0) // memmove(events, &events[1], nevents * sizeof(events_t));