xref: /plan9/sys/src/9/pc/devpccard.c (revision aa72973a2891ccbd3fb042462446761159389e19)
1 /*
2      cardbus and pcmcia (grmph) support.
3 */
4 #include "u.h"
5 #include "../port/lib.h"
6 #include "mem.h"
7 #include "dat.h"
8 #include "fns.h"
9 #include "../port/error.h"
10 #include "io.h"
11 
12 #define DEBUG	0
13 
14 #pragma	varargck	type	"T"	int
15 
16 #define MAP(x,o)	(Rmap + (x)*0x8 + o)
17 
18 enum {
19 	TI_vid = 0x104c,
20 	TI_1131_did = 0xAC15,
21 	TI_1250_did = 0xAC16,
22 	TI_1450_did = 0xAC1B,
23 	TI_1251A_did = 0xAC1D,
24 	TI_1420_did = 0xAC51,
25 
26 	Ricoh_vid = 0x1180,
27 	Ricoh_475_did = 0x0475,
28 	Ricoh_476_did = 0x0476,
29 	Ricoh_478_did = 0x0478,
30 
31 	O2_vid = 0x1217,
32 	O2_OZ711M3_did = 0x7134,
33 
34 	Nslots = 4,		/* Maximum number of CardBus slots to use */
35 
36 	K = 1024,
37 	M = K * K,
38 
39 	LegacyAddr = 0x3e0,
40 	NUMEVENTS = 10,
41 
42 	TI1131xSC = 0x80,		/* system control */
43 		TI122X_SC_INTRTIE = 1 << 29,
44 	TI12xxIM = 0x8c,		/*  */
45 	TI1131xCC = 0x91,		/* card control */
46 		TI113X_CC_RIENB = 1 << 7,
47 		TI113X_CC_ZVENABLE = 1 << 6,
48 		TI113X_CC_PCI_IRQ_ENA = 1 << 5,
49 		TI113X_CC_PCI_IREQ = 1 << 4,
50 		TI113X_CC_PCI_CSC = 1 << 3,
51 		TI113X_CC_SPKROUTEN = 1 << 1,
52 		TI113X_CC_IFG = 1 << 0,
53 	TI1131xDC = 0x92,		/* device control */
54 };
55 
56 typedef struct Variant Variant;
57 struct Variant {
58 	ushort	vid;
59 	ushort	did;
60 	char	*name;
61 };
62 
63 static Variant variant[] = {
64 {	Ricoh_vid,	Ricoh_475_did,	"Ricoh 475 PCI/Cardbus bridge",	},
65 {	Ricoh_vid,	Ricoh_476_did,	"Ricoh 476 PCI/Cardbus bridge",	},
66 {	Ricoh_vid,	Ricoh_478_did,	"Ricoh 478 PCI/Cardbus bridge",	},
67 {	TI_vid,		TI_1131_did,	"TI PCI-1131 Cardbus Controller", },
68 {	TI_vid,		TI_1250_did,	"TI PCI-1250 Cardbus Controller", },
69 {	TI_vid,		TI_1450_did,	"TI PCI-1450 Cardbus Controller", },
70 {	TI_vid,		TI_1251A_did,	"TI PCI-1251A Cardbus Controller", },
71 {	TI_vid,		TI_1420_did,	"TI PCI-1420 Cardbus Controller", },
72 {	O2_vid,		O2_OZ711M3_did,	"O2Micro OZ711M3 MemoryCardBus", },
73 };
74 
75 /* Cardbus registers */
76 enum {
77 	SocketEvent = 0,
78 		SE_CCD = 3 << 1,
79 		SE_POWER = 1 << 3,
80 	SocketMask = 1,
81 	SocketState = 2,
82 		SS_CCD = 3 << 1,
83 		SS_POWER = 1 << 3,
84 		SS_PC16 = 1 << 4,
85 		SS_CBC = 1 << 5,
86 		SS_NOTCARD = 1 << 7,
87 		SS_BADVCC = 1 << 9,
88 		SS_5V = 1 << 10,
89 		SS_3V = 1 << 11,
90 	SocketForce = 3,
91 	SocketControl = 4,
92 		SC_5V = 0x22,
93 		SC_3V = 0x33,
94 };
95 
96 enum {
97 	PciPCR_IO = 1 << 0,
98 	PciPCR_MEM = 1 << 1,
99 	PciPCR_Master = 1 << 2,
100 
101 	PciPMC = 0xa4,
102 
103 	Nbars = 6,
104 	Ncmd = 10,
105 	CBIRQ = 9,
106 
107 	PC16,
108 	PC32,
109 };
110 
111 enum {
112 	Ti82365,
113 	Tpd6710,
114 	Tpd6720,
115 	Tvg46x,
116 };
117 
118 /*
119  *  Intel 82365SL PCIC controller for the PCMCIA or
120  *  Cirrus Logic PD6710/PD6720 which is mostly register compatible
121  */
122 enum
123 {
124 	/*
125 	 *  registers indices
126 	 */
127 	Rid=		0x0,		/* identification and revision */
128 	Ris=		0x1,		/* interface status */
129 	Rpc=	 	0x2,		/* power control */
130 	 Foutena=	 (1<<7),	/*  output enable */
131 	 Fautopower=	 (1<<5),	/*  automatic power switching */
132 	 Fcardena=	 (1<<4),	/*  PC card enable */
133 	Rigc= 		0x3,		/* interrupt and general control */
134 	 Fiocard=	 (1<<5),	/*  I/O card (vs memory) */
135 	 Fnotreset=	 (1<<6),	/*  reset if not set */
136 	 FSMIena=	 (1<<4),	/*  enable change interrupt on SMI */
137 	Rcsc= 		0x4,		/* card status change */
138 	Rcscic= 	0x5,		/* card status change interrupt config */
139 	 Fchangeena=	 (1<<3),	/*  card changed */
140 	 Fbwarnena=	 (1<<1),	/*  card battery warning */
141 	 Fbdeadena=	 (1<<0),	/*  card battery dead */
142 	Rwe= 		0x6,		/* address window enable */
143 	 Fmem16=	 (1<<5),	/*  use A23-A12 to decode address */
144 	Rio= 		0x7,		/* I/O control */
145 	 Fwidth16=	 (1<<0),	/*  16 bit data width */
146 	 Fiocs16=	 (1<<1),	/*  IOCS16 determines data width */
147 	 Fzerows=	 (1<<2),	/*  zero wait state */
148 	 Ftiming=	 (1<<3),	/*  timing register to use */
149 	Riobtm0lo=	0x8,		/* I/O address 0 start low byte */
150 	Riobtm0hi=	0x9,		/* I/O address 0 start high byte */
151 	Riotop0lo=	0xa,		/* I/O address 0 stop low byte */
152 	Riotop0hi=	0xb,		/* I/O address 0 stop high byte */
153 	Riobtm1lo=	0xc,		/* I/O address 1 start low byte */
154 	Riobtm1hi=	0xd,		/* I/O address 1 start high byte */
155 	Riotop1lo=	0xe,		/* I/O address 1 stop low byte */
156 	Riotop1hi=	0xf,		/* I/O address 1 stop high byte */
157 	Rmap=		0x10,		/* map 0 */
158 
159 	/*
160 	 *  CL-PD67xx extension registers
161 	 */
162 	Rmisc1=		0x16,		/* misc control 1 */
163 	 F5Vdetect=	 (1<<0),
164 	 Fvcc3V=	 (1<<1),
165 	 Fpmint=	 (1<<2),
166 	 Fpsirq=	 (1<<3),
167 	 Fspeaker=	 (1<<4),
168 	 Finpack=	 (1<<7),
169 	Rfifo=		0x17,		/* fifo control */
170 	 Fflush=	 (1<<7),	/*  flush fifo */
171 	Rmisc2=		0x1E,		/* misc control 2 */
172 	 Flowpow=	 (1<<1),	/*  low power mode */
173 	Rchipinfo=	0x1F,		/* chip information */
174 	Ratactl=	0x26,		/* ATA control */
175 
176 	/*
177 	 *  offsets into the system memory address maps
178 	 */
179 	Mbtmlo=		0x0,		/* System mem addr mapping start low byte */
180 	Mbtmhi=		0x1,		/* System mem addr mapping start high byte */
181 	 F16bit=	 (1<<7),	/*  16-bit wide data path */
182 	Mtoplo=		0x2,		/* System mem addr mapping stop low byte */
183 	Mtophi=		0x3,		/* System mem addr mapping stop high byte */
184 	 Ftimer1=	 (1<<6),	/*  timer set 1 */
185 	Mofflo=		0x4,		/* Card memory offset address low byte */
186 	Moffhi=		0x5,		/* Card memory offset address high byte */
187 	 Fregactive=	 (1<<6),	/*  attribute memory */
188 
189 	/*
190 	 *  configuration registers - they start at an offset in attribute
191 	 *  memory found in the CIS.
192 	 */
193 	Rconfig=	0,
194 	 Creset=	 (1<<7),	/*  reset device */
195 	 Clevel=	 (1<<6),	/*  level sensitive interrupt line */
196 };
197 
198 /*
199  *  read and crack the card information structure enough to set
200  *  important parameters like power
201  */
202 /* cis memory walking */
203 typedef struct Cisdat Cisdat;
204 struct Cisdat {
205 	uchar		*cisbase;
206 	int		cispos;
207 	int		cisskip;
208 	int		cislen;
209 };
210 
211 typedef struct Pcminfo Pcminfo;
212 struct Pcminfo {
213 	char		verstr[512];		/* Version string */
214 	PCMmap		mmap[4];		/* maps, last is always for the kernel */
215 	ulong		conf_addr;		/* Config address */
216 	uchar		conf_present;		/* Config register present */
217 	int		nctab;			/* In use configuration tables */
218 	PCMconftab	ctab[8];		/* Configuration tables */
219 	PCMconftab	*defctab;		/* Default conftab */
220 
221 	int		port;			/* Actual port usage */
222 	int		irq;			/* Actual IRQ usage */
223 };
224 
225 typedef struct Cardbus Cardbus;
226 struct Cardbus {
227 	Lock;
228 	Variant		*variant;		/* Which CardBus chipset */
229 	Pcidev		*pci;			/* The bridge itself */
230 	ulong		*regs;			/* Cardbus registers */
231 	int		ltype;			/* Legacy type */
232 	int		lindex;			/* Legacy port index address */
233 	int		ldata;			/* Legacy port data address */
234 	int		lbase;			/* Base register for this socket */
235 
236 	int		state;			/* Current state of card */
237 	int		type;			/* Type of card */
238 	Pcminfo		linfo;			/* PCMCIA slot info */
239 
240 	int		special;		/* card is allocated to a driver */
241 
242 	int		refs;			/* Number of refs to slot */
243 	Lock		refslock;		/* inc/dev ref lock */
244 };
245 
246 static int managerstarted;
247 
248 enum {
249 	Mshift=	12,
250 	Mgran=	(1<<Mshift),	/* granularity of maps */
251 	Mmask=	~(Mgran-1),	/* mask for address bits important to the chip */
252 };
253 
254 static Cardbus cbslots[Nslots];
255 static int nslots;
256 
257 static ulong exponent[8] = {
258 	1, 10, 100, 1000, 10000, 100000, 1000000, 10000000,
259 };
260 
261 static ulong vmant[16] = {
262 	10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90,
263 };
264 
265 static ulong mantissa[16] = {
266 	0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80,
267 };
268 
269 static char Enocard[] = "No card in slot";
270 
271 enum
272 {
273 	CMdown,
274 	CMpower,
275 };
276 
277 static Cmdtab pccardctlmsg[] =
278 {
279 	CMdown,		"down",	2,
280 	CMpower,	"power",	1,
281 };
282 
283 static int powerup(Cardbus *);
284 static void configure(Cardbus *);
285 static void powerdown(Cardbus *cb);
286 static void unconfigure(Cardbus *cb);
287 
288 static void i82365probe(Cardbus *cb, int lindex, int ldata);
289 static void i82365configure(Cardbus *cb);
290 static PCMmap *isamap(Cardbus *cb, ulong offset, int len, int attr);
291 static void isaunmap(PCMmap* m);
292 static uchar rdreg(Cardbus *cb, int index);
293 static void wrreg(Cardbus *cb, int index, uchar val);
294 static int readc(Cisdat *cis, uchar *x);
295 static void tvers1(Cardbus *cb, Cisdat *cis, int );
296 static void tcfig(Cardbus *cb, Cisdat *cis, int );
297 static void tentry(Cardbus *cb, Cisdat *cis, int );
298 static int vcode(int volt);
299 static int pccard_pcmspecial(char *idstr, ISAConf *isa);
300 static void pccard_pcmspecialclose(int slotno);
301 
302 enum {
303 	CardDetected,
304 	CardPowered,
305 	CardEjected,
306 	CardConfigured,
307 };
308 
309 static char *messages[] = {
310 [CardDetected]		"CardDetected",
311 [CardPowered]		"CardPowered",
312 [CardEjected]		"CardEjected",
313 [CardConfigured]	"CardConfigured",
314 };
315 
316 enum {
317 	SlotEmpty,
318 	SlotFull,
319 	SlotPowered,
320 	SlotConfigured,
321 };
322 
323 static char *states[] = {
324 [SlotEmpty]		"SlotEmpty",
325 [SlotFull]		"SlotFull",
326 [SlotPowered]		"SlotPowered",
327 [SlotConfigured]	"SlotConfigured",
328 };
329 
330 static void
engine(Cardbus * cb,int message)331 engine(Cardbus *cb, int message)
332 {
333 	if(DEBUG)
334 		print("engine(%ld): %s(%s)\n", cb - cbslots,
335 			states[cb->state], messages[message]);
336 	switch (cb->state) {
337 	case SlotEmpty:
338 
339 		switch (message) {
340 		case CardDetected:
341 			cb->state = SlotFull;
342 			powerup(cb);
343 			break;
344 		case CardEjected:
345 			break;
346 		default:
347 			if(DEBUG)
348 				print("#Y%ld: Invalid message %s in SlotEmpty state\n",
349 					cb - cbslots, messages[message]);
350 			break;
351 		}
352 		break;
353 
354 	case SlotFull:
355 
356 		switch (message) {
357 		case CardPowered:
358 			cb->state = SlotPowered;
359 			configure(cb);
360 			break;
361 		case CardEjected:
362 			cb->state = SlotEmpty;
363 			powerdown(cb);
364 			break;
365 		default:
366 			if(DEBUG)
367 				print("#Y%ld: Invalid message %s in SlotFull state\n",
368 					cb - cbslots, messages[message]);
369 			break;
370 		}
371 		break;
372 
373 	case SlotPowered:
374 
375 		switch (message) {
376 		case CardConfigured:
377 			cb->state = SlotConfigured;
378 			break;
379 		case CardEjected:
380 			cb->state = SlotEmpty;
381 			unconfigure(cb);
382 			powerdown(cb);
383 			break;
384 		default:
385 			print("#Y%ld: Invalid message %s in SlotPowered state\n",
386 				cb - cbslots, messages[message]);
387 			break;
388 		}
389 		break;
390 
391 	case SlotConfigured:
392 
393 		switch (message) {
394 		case CardEjected:
395 			cb->state = SlotEmpty;
396 			unconfigure(cb);
397 			powerdown(cb);
398 			break;
399 		default:
400 			if(DEBUG)
401 				print("#Y%ld: Invalid message %s in SlotConfigured state\n",
402 					cb - cbslots, messages[message]);
403 			break;
404 		}
405 		break;
406 	}
407 }
408 
409 static void
qengine(Cardbus * cb,int message)410 qengine(Cardbus *cb, int message)
411 {
412 	lock(cb);
413 	engine(cb, message);
414 	unlock(cb);
415 }
416 
417 typedef struct Events Events;
418 struct Events {
419 	Cardbus	*cb;
420 	int	message;
421 };
422 
423 static Lock levents;
424 static Events events[NUMEVENTS];
425 static Rendez revents;
426 static int nevents;
427 
428 static void
iengine(Cardbus * cb,int message)429 iengine(Cardbus *cb, int message)
430 {
431 	if (nevents >= NUMEVENTS) {
432 		print("#Y: Too many events queued, discarding request\n");
433 		return;
434 	}
435 	ilock(&levents);
436 	events[nevents].cb = cb;
437 	events[nevents].message = message;
438 	nevents++;
439 	iunlock(&levents);
440 	wakeup(&revents);
441 }
442 
443 static int
eventoccured(void)444 eventoccured(void)
445 {
446 	return nevents > 0;
447 }
448 
449 static void
processevents(void *)450 processevents(void *)
451 {
452 	while (1) {
453 		int message;
454 		Cardbus *cb;
455 
456 		sleep(&revents, (int (*)(void *))eventoccured, nil);
457 
458 		cb = nil;
459 		message = 0;
460 		ilock(&levents);
461 		if (nevents > 0) {
462 			cb = events[0].cb;
463 			message = events[0].message;
464 			nevents--;
465 			if (nevents > 0)
466 				memmove(events, &events[1], nevents * sizeof(Events));
467 		}
468 		iunlock(&levents);
469 
470 		if (cb)
471 			qengine(cb, message);
472 	}
473 }
474 
475 static void
cbinterrupt(Ureg *,void *)476 cbinterrupt(Ureg *, void *)
477 {
478 	int i;
479 
480 	for (i = 0; i != nslots; i++) {
481 		Cardbus *cb = &cbslots[i];
482 		ulong event, state;
483 
484 		event = cb->regs[SocketEvent];
485 		if(!(event & (SE_POWER|SE_CCD)))
486 			continue;
487 		state = cb->regs[SocketState];
488 		rdreg(cb, Rcsc);	/* Ack the interrupt */
489 
490 		if(DEBUG)
491 			print("#Y%ld: interrupt: event %.8lX, state %.8lX, (%s)\n",
492 				cb - cbslots, event, state, states[cb->state]);
493 
494 		if (event & SE_CCD) {
495 			cb->regs[SocketEvent] |= SE_CCD;	/* Ack interrupt */
496 			if (state & SE_CCD) {
497 				if (cb->state != SlotEmpty) {
498 					print("#Y: take cardejected interrupt\n");
499 					iengine(cb, CardEjected);
500 				}
501 			}
502 			else
503 				iengine(cb, CardDetected);
504 		}
505 
506 		if (event & SE_POWER) {
507 			cb->regs[SocketEvent] |= SE_POWER;	/* Ack interrupt */
508 			iengine(cb, CardPowered);
509 		}
510 	}
511 }
512 
513 void
devpccardlink(void)514 devpccardlink(void)
515 {
516 	static int initialized;
517 	Pcidev *pci;
518 	int i;
519 	uchar intl;
520 	char *p;
521 	void *baddrva;
522 
523 	if (initialized)
524 		return;
525 	initialized = 1;
526 
527 	if((p=getconf("pccard0")) && strncmp(p, "disabled", 8)==0)
528 		return;
529 
530 	if(_pcmspecial)
531 		return;
532 
533 	/* Allocate legacy space */
534 	if (ioalloc(LegacyAddr, 2, 0, "i82365.0") < 0)
535 		print("#Y: WARNING: Cannot allocate legacy ports\n");
536 
537 	/* Find all CardBus controllers */
538 	pci = nil;
539 	intl = 0xff;
540 	while ((pci = pcimatch(pci, 0, 0)) != nil) {
541 		ulong baddr;
542 		Cardbus *cb;
543 		int slot;
544 		uchar pin;
545 
546 		if(pci->ccrb != 6 || pci->ccru != 7)
547 			continue;
548 		for (i = 0; i != nelem(variant); i++)
549 			if (pci->vid == variant[i].vid && pci->did == variant[i].did)
550 				break;
551 		if (i == nelem(variant))
552 			continue;
553 
554 		/* initialize this slot */
555 		slot = nslots++;
556 		cb = &cbslots[slot];
557 
558 		cb->pci = pci;
559 		cb->variant = &variant[i];
560 
561 		if (pci->vid != TI_vid) {
562 			/*
563 			 * Gross hack, needs a fix.  Inherit the mappings from
564 			 * 9load for the TIs (pb)
565 			 */
566 			pcicfgw32(pci, PciCBMBR0, 0xffffffff);
567 			pcicfgw32(pci, PciCBMLR0, 0);
568 			pcicfgw32(pci, PciCBMBR1, 0xffffffff);
569 			pcicfgw32(pci, PciCBMLR1, 0);
570 			pcicfgw32(pci, PciCBIBR0, 0xffffffff);
571 			pcicfgw32(pci, PciCBILR0, 0);
572 			pcicfgw32(pci, PciCBIBR1, 0xffffffff);
573 			pcicfgw32(pci, PciCBILR1, 0);
574 		}
575 
576 		/* Set up PCI bus numbers if needed. */
577 		if (pcicfgr8(pci, PciSBN) == 0) {
578 			static int busbase = 0x20;
579 
580 			pcicfgw8(pci, PciSBN, busbase);
581 			pcicfgw8(pci, PciUBN, busbase + 2);
582 			busbase += 3;
583 		}
584 
585 		/* Patch up intl if needed. */
586 		if ((pin = pcicfgr8(pci, PciINTP)) != 0 &&
587 		    (pci->intl == 0xff || pci->intl == 0)) {
588 			pci->intl = pciipin(nil, pin);
589 			pcicfgw8(pci, PciINTL, pci->intl);
590 
591 			if (pci->intl == 0xff || pci->intl == 0)
592 				print("#Y%ld: No interrupt?\n", cb - cbslots);
593 		}
594 
595 		/* Don't you love standards! */
596 		if (pci->vid == TI_vid) {
597 			if (pci->did <= TI_1131_did) {
598 				uchar cc;
599 
600 				cc = pcicfgr8(pci, TI1131xCC);
601 				cc &= ~(TI113X_CC_PCI_IRQ_ENA |
602 					TI113X_CC_PCI_IREQ |
603 					TI113X_CC_PCI_CSC |
604 					TI113X_CC_ZVENABLE);
605 				cc |= TI113X_CC_PCI_IRQ_ENA |
606 					TI113X_CC_PCI_IREQ |
607 					TI113X_CC_SPKROUTEN;
608 				pcicfgw8(pci, TI1131xCC, cc);
609 
610 				/* PCI interrupts only */
611 				pcicfgw8(pci, TI1131xDC,
612 					pcicfgr8(pci, TI1131xDC) & ~6);
613 
614 				/* CSC ints to PCI bus. */
615 				wrreg(cb, Rigc, rdreg(cb, Rigc) | 0x10);
616 			}
617 			else if (pci->did == TI_1250_did) {
618 				print("No support yet for the TI_1250_did, prod pb\n");
619 			}
620 			else if (pci->did == TI_1420_did) {
621 				/* Disable Vcc protection */
622 				pcicfgw32(cb->pci, 0x80,
623 					pcicfgr32(cb->pci, 0x80) | (1 << 21));
624 			}
625 
626 			pcicfgw16(cb->pci, PciPMC, pcicfgr16(cb->pci, PciPMC) & ~3);
627 		}
628 		if (pci->vid == O2_vid) {
629 			if(DEBUG)
630 				print("writing O2 config\n");
631 			pcicfgw8(cb->pci, 0x94, 0xCA);
632 			pcicfgw8(cb->pci, 0xD4, 0xCA);
633 		}
634 
635 		if (intl != 0xff && intl != pci->intl)
636 			intrenable(pci->intl, cbinterrupt, cb, pci->tbdf, "cardbus");
637 		intl = pci->intl;
638 
639 		if ((baddr = pcicfgr32(cb->pci, PciBAR0)) == 0) {
640 			int size = (pci->did == Ricoh_478_did)? 0x10000: 0x1000;
641 
642 			baddr = upaalloc(size, size);
643 			baddrva = vmap(baddr, size);
644 			pcicfgw32(cb->pci, PciBAR0, baddr);
645 			cb->regs = (ulong *)baddrva;
646 		}
647 		else
648 			cb->regs = (ulong *)vmap(baddr, 4096);
649 		cb->state = SlotEmpty;
650 
651 		/* Don't really know what to do with this... */
652 		i82365probe(cb, LegacyAddr, LegacyAddr + 1);
653 
654 		print("#Y%ld: %s, %.8ulX intl %d\n", cb - cbslots,
655 			 variant[i].name, baddr, pci->intl);
656 	}
657 
658 	if (nslots == 0){
659 		iofree(LegacyAddr);
660 		return;
661 	}
662 
663 	_pcmspecial = pccard_pcmspecial;
664 	_pcmspecialclose = pccard_pcmspecialclose;
665 
666 	for (i = 0; i != nslots; i++) {
667 		Cardbus *cb = &cbslots[i];
668 
669 		if ((cb->regs[SocketState] & SE_CCD) == 0)
670 			engine(cb, CardDetected);
671 	}
672 
673 	delay(500);			/* Allow time for power up */
674 
675 	for (i = 0; i != nslots; i++) {
676 		Cardbus *cb = &cbslots[i];
677 
678 		if (cb->regs[SocketState] & SE_POWER)
679 			engine(cb, CardPowered);
680 
681 		/* Ack and enable interrupts on all events */
682 		// cb->regs[SocketEvent] = cb->regs[SocketEvent];
683 		cb->regs[SocketMask] |= 0xF;
684 		wrreg(cb, Rcscic, 0xC);
685 	}
686 }
687 
688 static int
powerup(Cardbus * cb)689 powerup(Cardbus *cb)
690 {
691 	ulong state;
692 	ushort bcr;
693 
694 	state = cb->regs[SocketState];
695 	if (state & SS_PC16) {
696 		if(DEBUG)
697 			print("#Y%ld: Probed a PC16 card, powering up card\n",
698 				cb - cbslots);
699 		cb->type = PC16;
700 		memset(&cb->linfo, 0, sizeof(Pcminfo));
701 
702 		/* power up and unreset, wait's are empirical (???) */
703 		wrreg(cb, Rpc, Fautopower|Foutena|Fcardena);
704 		delay(300);
705 		wrreg(cb, Rigc, 0);
706 		delay(100);
707 		wrreg(cb, Rigc, Fnotreset);
708 		delay(500);
709 
710 //		return 1;
711 	}
712 
713 	if (state & SS_CCD)
714 		return 0;
715 
716 	if (state & SS_NOTCARD) {
717 		print("#Y%ld: No card inserted\n", cb - cbslots);
718 		return 0;
719 	}
720 
721 	if ((state & SS_3V) == 0 && (state & SS_5V) == 0) {
722 		print("#Y%ld: Unsupported voltage, powering down card!\n",
723 			cb - cbslots);
724 		cb->regs[SocketControl] = 0;
725 		return 0;
726 	}
727 
728 	if(DEBUG)
729 		print("#Y%ld: card %spowered at %d volt\n", cb - cbslots,
730 			(state & SS_POWER)? "": "not ",
731 			(state & SS_3V)? 3: (state & SS_5V)? 5: -1);
732 
733 	/* Power up the card
734 	 * and make sure the secondary bus is not in reset.
735 	 */
736 	cb->regs[SocketControl] = (state & SS_5V)? SC_5V: SC_3V;
737 	delay(50);
738 	bcr = pcicfgr16(cb->pci, PciBCR);
739 	bcr &= ~0x40;
740 	pcicfgw16(cb->pci, PciBCR, bcr);
741 	delay(100);
742 
743 	if (state & SS_PC16)
744 		cb->type = PC16;
745 	else
746 		cb->type = PC32;
747 
748 	return 1;
749 }
750 
751 static void
powerdown(Cardbus * cb)752 powerdown(Cardbus *cb)
753 {
754 	ushort bcr;
755 
756 	if (cb->type == PC16) {
757 
758 		wrreg(cb, Rpc, 0);	/* turn off card power */
759 		wrreg(cb, Rwe, 0);	/* no windows */
760 
761 		cb->type = -1;
762 		return;
763 	}
764 
765 	bcr = pcicfgr16(cb->pci, PciBCR);
766 	bcr |= 0x40;
767 	pcicfgw16(cb->pci, PciBCR, bcr);
768 	cb->regs[SocketControl] = 0;
769 	cb->type = -1;
770 }
771 
772 static void
configure(Cardbus * cb)773 configure(Cardbus *cb)
774 {
775 	int i, r;
776 	ulong size, bar;
777 	Pcidev *pci;
778 	ulong membase, iobase, memlen, iolen, rombase, romlen;
779 
780 	if(DEBUG)
781 		print("configuring slot %ld (%s)\n", cb - cbslots, states[cb->state]);
782 	if (cb->state == SlotConfigured)
783 		return;
784 	engine(cb, CardConfigured);
785 
786 	delay(50);					/* Emperically established */
787 
788 	if (cb->type == PC16) {
789 		i82365configure(cb);
790 		return;
791 	}
792 
793 	/* Scan the CardBus for new PCI devices */
794 	pciscan(pcicfgr8(cb->pci, PciSBN), &cb->pci->bridge);
795 
796 	/*
797 	 * size the devices on the bus, reserve a minimum for devices arriving later,
798 	 * allow for ROM space, allocate space, and set the cardbus mapping registers
799 	 */
800 	pcibussize(cb->pci->bridge, &memlen, &iolen);	/* TO DO: need initial alignments */
801 
802 	romlen = 0;
803 	for(pci = cb->pci->bridge; pci != nil; pci = pci->list){
804 		size = pcibarsize(pci, PciEBAR0);
805 		if(size > 0){
806 			pci->rom.bar = -1;
807 			pci->rom.size = size;
808 			romlen += size;
809 		}
810 	}
811 
812 	if(iolen < 512)
813 		iolen = 512;
814 	iobase = ioreserve(~0, iolen, 0, "cardbus");
815 	pcicfgw32(cb->pci, PciCBIBR0, iobase);
816 	pcicfgw32(cb->pci, PciCBILR0, iobase + iolen-1);
817 	pcicfgw32(cb->pci, PciCBIBR1, 0);
818 	pcicfgw32(cb->pci, PciCBILR1, 0);
819 
820 	rombase = memlen;
821 	memlen += romlen;
822 	if(memlen < 1*1024*1024)
823 		memlen = 1*1024*1024;
824 	membase = upaalloc(memlen, 4*1024*1024);	/* TO DO: better alignment */
825 	pcicfgw32(cb->pci, PciCBMBR0, membase);
826 	pcicfgw32(cb->pci, PciCBMLR0, membase + memlen-1);
827 	pcicfgw32(cb->pci, PciCBMBR1, 0);
828 	pcicfgw32(cb->pci, PciCBMLR1, 0);
829 
830 //	pcibussize(cb->pci->bridge, &membase, &iobase);	/* now assign them */
831 	rombase += membase;
832 
833 	for(pci = cb->pci->bridge; pci != nil; pci = pci->list){
834 		r = pcicfgr16(pci, PciPCR);
835 		r &= ~(PciPCR_IO|PciPCR_MEM);
836 		pcicfgw16(pci, PciPCR, r);
837 
838 		/*
839 		 * Treat the found device as an ordinary PCI card.
840 		 * It seems that the CIS is not always present in
841 		 * CardBus cards.
842 		 * XXX, need to support multifunction cards
843 		 */
844 		for(i = 0; i < Nbars; i++) {
845 			if(pci->mem[i].size == 0)
846 				continue;
847 			bar = pci->mem[i].bar;
848 			if(bar & 1)
849 				bar += iobase;
850 			else
851 				bar += membase;
852 			pci->mem[i].bar = bar;
853 			pcicfgw32(pci, PciBAR0 + 4*i, bar);
854 			if((bar & 1) == 0){
855 				print("%T mem[%d] %8.8lux %d\n", pci->tbdf, i, bar, pci->mem[i].size);
856 				if(bar & 0x80){	/* TO DO: enable prefetch */
857 					;
858 				}
859 			}
860 		}
861 		if((size = pcibarsize(pci, PciEBAR0)) > 0) {	/* TO DO: can this be done by pci.c? */
862 			pci->rom.bar = rombase;
863 			pci->rom.size = size;
864 			rombase += size;
865 			pcicfgw32(pci, PciEBAR0, pci->rom.bar);
866 		}
867 
868 		/* Set the basic PCI registers for the device */
869 		pci->pcr = pcicfgr16(pci, PciPCR);
870 		pci->pcr |= PciPCR_IO|PciPCR_MEM|PciPCR_Master;
871 		pci->cls = 8;
872 		pci->ltr = 64;
873 		pcicfgw16(pci, PciPCR, pci->pcr);
874 		pcicfgw8(pci, PciCLS, pci->cls);
875 		pcicfgw8(pci, PciLTR, pci->ltr);
876 
877 		if (pcicfgr8(pci, PciINTP)) {
878 			pci->intl = pcicfgr8(cb->pci, PciINTL);
879 			pcicfgw8(pci, PciINTL, pci->intl);
880 
881 			/* Route interrupts to INTA#/B# */
882 			pcicfgw16(cb->pci, PciBCR,
883 					  pcicfgr16(cb->pci, PciBCR) & ~(1 << 7));
884 		}
885 	}
886 }
887 
888 static void
unconfigure(Cardbus * cb)889 unconfigure(Cardbus *cb)
890 {
891 	Pcidev *pci;
892 	int i, ioindex, memindex, r;
893 
894 	if (cb->type == PC16) {
895 		print("#Y%d: Don't know how to unconfigure a PC16 card\n",
896 			 (int)(cb - cbslots));
897 
898 		memset(&cb->linfo, 0, sizeof(Pcminfo));
899 		return;
900 	}
901 
902 	pci = cb->pci->bridge;
903 	if (pci == nil)
904 		return;		/* Not configured */
905 	cb->pci->bridge = nil;
906 
907 	memindex = ioindex = 0;
908 	while (pci) {
909 		Pcidev *_pci;
910 
911 		for (i = 0; i != Nbars; i++) {
912 			if (pci->mem[i].size == 0)
913 				continue;
914 			if (pci->mem[i].bar & 1) {
915 				iofree(pci->mem[i].bar & ~1);
916 				pcicfgw16(cb->pci, PciCBIBR0 + ioindex * 8,
917 						 (ushort)-1);
918 				pcicfgw16(cb->pci, PciCBILR0 + ioindex * 8, 0);
919 				ioindex++;
920 				continue;
921 			}
922 
923 			upafree(pci->mem[i].bar & ~0xF, pci->mem[i].size);
924 			pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
925 			pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
926 			r = pcicfgr16(cb->pci, PciBCR);
927 			r &= ~(1 << (8 + memindex));
928 			pcicfgw16(cb->pci, PciBCR, r);
929 			memindex++;
930 		}
931 
932 		if (pci->rom.bar && memindex < 2) {
933 			upafree(pci->rom.bar & ~0xF, pci->rom.size);
934 			pcicfgw32(cb->pci, PciCBMBR0 + memindex * 8, (ulong)-1);
935 			pcicfgw32(cb->pci, PciCBMLR0 + memindex * 8, 0);
936 			memindex++;
937 		}
938 
939 		_pci = pci->list;
940 		free(_pci);
941 		pci = _pci;
942 	}
943 }
944 
945 static void
i82365configure(Cardbus * cb)946 i82365configure(Cardbus *cb)
947 {
948 	int this;
949 	Cisdat cis;
950 	PCMmap *m;
951 	uchar type, link;
952 
953 	/*
954 	 * Read all tuples in attribute space.
955 	 */
956 	m = isamap(cb, 0, 0, 1);
957 	if(m == 0)
958 		return;
959 
960 	cis.cisbase = KADDR(m->isa);
961 	cis.cispos = 0;
962 	cis.cisskip = 2;
963 	cis.cislen = m->len;
964 
965 	/* loop through all the tuples */
966 	for(;;){
967 		this = cis.cispos;
968 		if(readc(&cis, &type) != 1)
969 			break;
970 		if(type == 0xFF)
971 			break;
972 		if(readc(&cis, &link) != 1)
973 			break;
974 
975 		switch(type){
976 		default:
977 			break;
978 		case 0x15:
979 			tvers1(cb, &cis, type);
980 			break;
981 		case 0x1A:
982 			tcfig(cb, &cis, type);
983 			break;
984 		case 0x1B:
985 			tentry(cb, &cis, type);
986 			break;
987 		}
988 
989 		if(link == 0xFF)
990 			break;
991 		cis.cispos = this + (2+link);
992 	}
993 	isaunmap(m);
994 }
995 
996 /*
997  *  look for a card whose version contains 'idstr'
998  */
999 static int
pccard_pcmspecial(char * idstr,ISAConf * isa)1000 pccard_pcmspecial(char *idstr, ISAConf *isa)
1001 {
1002 	int i, irq;
1003 	PCMconftab *ct, *et;
1004 	Pcminfo *pi;
1005 	Cardbus *cb;
1006 	uchar x, we, *p;
1007 
1008 	cb = nil;
1009 	for (i = 0; i != nslots; i++) {
1010 		cb = &cbslots[i];
1011 
1012 		lock(cb);
1013 		if (cb->state == SlotConfigured &&
1014 		    cb->type == PC16 &&
1015 		    !cb->special &&
1016 		    strstr(cb->linfo.verstr, idstr))
1017 			break;
1018 		unlock(cb);
1019 	}
1020 
1021 	if (i == nslots) {
1022 		if(0 && DEBUG)
1023 			print("#Y: %s not found\n", idstr);
1024 		return -1;
1025 	}
1026 
1027 	pi = &cb->linfo;
1028 
1029 	/*
1030  	  *  configure the PCMslot for IO.  We assume very heavily that we can read
1031  	  *  configuration info from the CIS.  If not, we won't set up correctly.
1032  	  */
1033 	irq = isa->irq;
1034 	if(irq == 2)
1035 		irq = 9;
1036 
1037 	et = &pi->ctab[pi->nctab];
1038 	ct = nil;
1039 	for(i = 0; i < isa->nopt; i++){
1040 		int index;
1041 		char *cp;
1042 
1043 		if(strncmp(isa->opt[i], "index=", 6))
1044 			continue;
1045 		index = strtol(&isa->opt[i][6], &cp, 0);
1046 		if(cp == &isa->opt[i][6] || index >= pi->nctab) {
1047 			unlock(cb);
1048 			print("#Y%d: Cannot find index %d in conf table\n",
1049 				 (int)(cb - cbslots), index);
1050 			return -1;
1051 		}
1052 		ct = &pi->ctab[index];
1053 	}
1054 
1055 	if(ct == nil){
1056 		PCMconftab *t;
1057 
1058 		/* assume default is right */
1059 		if(pi->defctab)
1060 			ct = pi->defctab;
1061 		else
1062 			ct = pi->ctab;
1063 
1064 		/* try for best match */
1065 		if(ct->nio == 0
1066 		|| ct->io[0].start != isa->port || ((1<<irq) & ct->irqs) == 0){
1067 			for(t = pi->ctab; t < et; t++)
1068 				if(t->nio
1069 				&& t->io[0].start == isa->port
1070 				&& ((1<<irq) & t->irqs)){
1071 					ct = t;
1072 					break;
1073 				}
1074 		}
1075 		if(ct->nio == 0 || ((1<<irq) & ct->irqs) == 0){
1076 			for(t = pi->ctab; t < et; t++)
1077 				if(t->nio && ((1<<irq) & t->irqs)){
1078 					ct = t;
1079 					break;
1080 				}
1081 		}
1082 		if(ct->nio == 0){
1083 			for(t = pi->ctab; t < et; t++)
1084 				if(t->nio){
1085 					ct = t;
1086 					break;
1087 				}
1088 		}
1089 	}
1090 
1091 	if(ct == et || ct->nio == 0) {
1092 		unlock(cb);
1093 		print("#Y%d: No configuration?\n", (int)(cb - cbslots));
1094 		return -1;
1095 	}
1096 	if(isa->port == 0 && ct->io[0].start == 0) {
1097 		unlock(cb);
1098 		print("#Y%d: No part or start address\n", (int)(cb - cbslots));
1099 		return -1;
1100 	}
1101 
1102 	cb->special = 1;	/* taken */
1103 
1104 	/* route interrupts */
1105 	isa->irq = irq;
1106 	wrreg(cb, Rigc, irq | Fnotreset | Fiocard);
1107 
1108 	/* set power and enable device */
1109 	x = vcode(ct->vpp1);
1110 	wrreg(cb, Rpc, x|Fautopower|Foutena|Fcardena);
1111 
1112 	/* 16-bit data path */
1113 	if(ct->bit16)
1114 		x = Ftiming|Fiocs16|Fwidth16;
1115 	else
1116 		x = Ftiming;
1117 	if(ct->nio == 2 && ct->io[1].start)
1118 		x |= x<<4;
1119 	wrreg(cb, Rio, x);
1120 
1121 	/*
1122 	 * enable io port map 0
1123 	 * the 'top' register value includes the last valid address
1124 	 */
1125 	if(isa->port == 0)
1126 		isa->port = ct->io[0].start;
1127 	we = rdreg(cb, Rwe);
1128 	wrreg(cb, Riobtm0lo, isa->port);
1129 	wrreg(cb, Riobtm0hi, isa->port>>8);
1130 	i = isa->port+ct->io[0].len-1;
1131 	wrreg(cb, Riotop0lo, i);
1132 	wrreg(cb, Riotop0hi, i>>8);
1133 	we |= 1<<6;
1134 	if(ct->nio == 2 && ct->io[1].start){
1135 		wrreg(cb, Riobtm1lo, ct->io[1].start);
1136 		wrreg(cb, Riobtm1hi, ct->io[1].start>>8);
1137 		i = ct->io[1].start+ct->io[1].len-1;
1138 		wrreg(cb, Riotop1lo, i);
1139 		wrreg(cb, Riotop1hi, i>>8);
1140 		we |= 1<<7;
1141 	}
1142 	wrreg(cb, Rwe, we);
1143 
1144 	/* only touch Rconfig if it is present */
1145 	if(pi->conf_present & (1<<Rconfig)){
1146 		PCMmap *m;
1147 
1148 		/*  Reset adapter */
1149 		m = isamap(cb, pi->conf_addr + Rconfig, 1, 1);
1150 		p = KADDR(m->isa + pi->conf_addr + Rconfig - m->ca);
1151 
1152 		/* set configuration and interrupt type */
1153 		x = ct->index;
1154 		if(ct->irqtype & 0x20)
1155 			x |= Clevel;
1156 		*p = x;
1157 		delay(5);
1158 
1159 		isaunmap(m);
1160 	}
1161 
1162 	pi->port = isa->port;
1163 	pi->irq = isa->irq;
1164 	unlock(cb);
1165 
1166 	print("#Y%ld: %s irq %d, port %lX\n", cb - cbslots, pi->verstr, isa->irq, isa->port);
1167 	return (int)(cb - cbslots);
1168 }
1169 
1170 static void
pccard_pcmspecialclose(int slotno)1171 pccard_pcmspecialclose(int slotno)
1172 {
1173 	Cardbus *cb = &cbslots[slotno];
1174 
1175 	wrreg(cb, Rwe, 0);	/* no windows */
1176 	cb->special = 0;
1177 }
1178 
1179 static Chan*
pccardattach(char * spec)1180 pccardattach(char *spec)
1181 {
1182 	if (!managerstarted) {
1183 		managerstarted = 1;
1184 		kproc("cardbus", processevents, nil);
1185 	}
1186 	return devattach('Y', spec);
1187 }
1188 
1189 enum
1190 {
1191 	Qdir,
1192 	Qctl,
1193 
1194 	Nents = 1,
1195 };
1196 
1197 #define SLOTNO(c)	((ulong)((c->qid.path>>8)&0xff))
1198 #define TYPE(c)	((ulong)(c->qid.path&0xff))
1199 #define QID(s,t)	(((s)<<8)|(t))
1200 
1201 static int
pccardgen(Chan * c,char *,Dirtab *,int,int i,Dir * dp)1202 pccardgen(Chan *c, char*, Dirtab *, int , int i, Dir *dp)
1203 {
1204 	int slotno;
1205 	Qid qid;
1206 	long len;
1207 	int entry;
1208 
1209 	if(i == DEVDOTDOT){
1210 		mkqid(&qid, Qdir, 0, QTDIR);
1211 		devdir(c, qid, "#Y", 0, eve, 0555, dp);
1212 		return 1;
1213 	}
1214 
1215 	len = 0;
1216 	if(i >= Nents * nslots) return -1;
1217 	slotno = i / Nents;
1218 	entry = i % Nents;
1219 	if (entry == 0) {
1220 		qid.path = QID(slotno, Qctl);
1221 		snprint(up->genbuf, sizeof up->genbuf, "cb%dctl", slotno);
1222 	}
1223 	else {
1224 		/* Entries for memory regions.  I'll implement them when
1225 		     needed. (pb) */
1226 	}
1227 	qid.vers = 0;
1228 	qid.type = QTFILE;
1229 	devdir(c, qid, up->genbuf, len, eve, 0660, dp);
1230 	return 1;
1231 }
1232 
1233 static Walkqid*
pccardwalk(Chan * c,Chan * nc,char ** name,int nname)1234 pccardwalk(Chan *c, Chan *nc, char **name, int nname)
1235 {
1236 	return devwalk(c, nc, name, nname, 0, 0, pccardgen);
1237 }
1238 
1239 static int
pccardstat(Chan * c,uchar * db,int n)1240 pccardstat(Chan *c, uchar *db, int n)
1241 {
1242 	return devstat(c, db, n, 0, 0, pccardgen);
1243 }
1244 
1245 static void
increfp(Cardbus * cb)1246 increfp(Cardbus *cb)
1247 {
1248 	lock(&cb->refslock);
1249 	cb->refs++;
1250 	unlock(&cb->refslock);
1251 }
1252 
1253 static void
decrefp(Cardbus * cb)1254 decrefp(Cardbus *cb)
1255 {
1256 	lock(&cb->refslock);
1257 	cb->refs--;
1258 	unlock(&cb->refslock);
1259 }
1260 
1261 static Chan*
pccardopen(Chan * c,int omode)1262 pccardopen(Chan *c, int omode)
1263 {
1264 	if (c->qid.type & QTDIR){
1265 		if(omode != OREAD)
1266 			error(Eperm);
1267 	} else
1268 		increfp(&cbslots[SLOTNO(c)]);
1269 	c->mode = openmode(omode);
1270 	c->flag |= COPEN;
1271 	c->offset = 0;
1272 	return c;
1273 }
1274 
1275 static void
pccardclose(Chan * c)1276 pccardclose(Chan *c)
1277 {
1278 	if(c->flag & COPEN)
1279 		if((c->qid.type & QTDIR) == 0)
1280 			decrefp(&cbslots[SLOTNO(c)]);
1281 }
1282 
1283 static long
pccardread(Chan * c,void * a,long n,vlong offset)1284 pccardread(Chan *c, void *a, long n, vlong offset)
1285 {
1286 	Cardbus *cb;
1287 	char *buf, *p, *e;
1288 	int i;
1289 
1290 	switch(TYPE(c)){
1291 	case Qdir:
1292 		return devdirread(c, a, n, 0, 0, pccardgen);
1293 
1294 	case Qctl:
1295 		buf = p = malloc(READSTR);
1296 		if(p == nil)
1297 			error(Enomem);
1298 		buf[0] = 0;
1299 		e = p + READSTR;
1300 
1301 		cb = &cbslots[SLOTNO(c)];
1302 		lock(cb);
1303 		p = seprint(p, e, "slot %ld: %s; ", cb - cbslots, states[cb->state]);
1304 
1305 		switch (cb->type) {
1306 		case -1:
1307 			seprint(p, e, "\n");
1308 			break;
1309 
1310 		case PC32:
1311 			if (cb->pci->bridge) {
1312 				Pcidev *pci = cb->pci->bridge;
1313 				int i;
1314 
1315 				while (pci) {
1316 					p = seprint(p, e, "%.4uX %.4uX; irq %d\n",
1317 							  pci->vid, pci->did, pci->intl);
1318 					for (i = 0; i != Nbars; i++)
1319 						if (pci->mem[i].size)
1320 							p = seprint(p, e,
1321 									  "\tmem[%d] %.8ulX (%.8uX)\n",
1322 									  i, pci->mem[i].bar,
1323 									  pci->mem[i].size);
1324 					if (pci->rom.size)
1325 						p = seprint(p, e, "\tROM %.8ulX (%.8uX)\n",
1326 								  pci->rom.bar, pci->rom.size);
1327 					pci = pci->list;
1328 				}
1329 			}
1330 			break;
1331 
1332 		case PC16:
1333 			if (cb->state == SlotConfigured) {
1334 				Pcminfo *pi = &cb->linfo;
1335 
1336 				p = seprint(p, e, "%s port %X; irq %d;\n",
1337 						  pi->verstr, pi->port,
1338 						  pi->irq);
1339 				for (i = 0; i != pi->nctab; i++) {
1340 					PCMconftab *ct;
1341 					int j;
1342 
1343 					ct = &pi->ctab[i];
1344 					p = seprint(p, e,
1345 						"\tconfiguration[%d] irqs %.4uX; vpp %d, %d; %s\n",
1346 							  i, ct->irqs, ct->vpp1, ct->vpp2,
1347 							  (ct == pi->defctab)? "(default);": "");
1348 					for (j = 0; j != ct->nio; j++)
1349 						if (ct->io[j].len > 0)
1350 							p = seprint(p, e, "\t\tio[%d] %.8ulX %uld\n",
1351 									  j, ct->io[j].start, ct->io[j].len);
1352 				}
1353 			}
1354 			break;
1355 		}
1356 		unlock(cb);
1357 
1358 		n = readstr(offset, a, n, buf);
1359 		free(buf);
1360 		return n;
1361 	}
1362 	return 0;
1363 }
1364 
1365 static long
pccardwrite(Chan * c,void * v,long n,vlong)1366 pccardwrite(Chan *c, void *v, long n, vlong)
1367 {
1368 	Rune r;
1369 	ulong n0;
1370 	char *device;
1371 	Cmdbuf *cbf;
1372 	Cmdtab *ct;
1373 	Cardbus *cb;
1374 
1375 	n0 = n;
1376 	switch(TYPE(c)){
1377 	case Qctl:
1378 		cb = &cbslots[SLOTNO(c)];
1379 
1380 		cbf = parsecmd(v, n);
1381 		if(waserror()){
1382 			free(cbf);
1383 			nexterror();
1384 		}
1385 		ct = lookupcmd(cbf, pccardctlmsg, nelem(pccardctlmsg));
1386 		switch(ct->index){
1387 		case CMdown:
1388 			device = cbf->f[1];
1389 			device += chartorune(&r, device);
1390 			if ((n = devno(r, 1)) >= 0 && devtab[n]->config)
1391 				devtab[n]->config(0, device, nil);
1392 			qengine(cb, CardEjected);
1393 			break;
1394 		case CMpower:
1395 			if ((cb->regs[SocketState] & SS_CCD) == 0)
1396 				qengine(cb, CardDetected);
1397 			break;
1398 		}
1399 		poperror();
1400 		free(cbf);
1401 		break;
1402 	}
1403 	return n0 - n;
1404 }
1405 
1406 Dev pccarddevtab = {
1407 	'Y',
1408 	"cardbus",
1409 
1410 	devreset,
1411 	devinit,
1412 	devshutdown,
1413 	pccardattach,
1414 	pccardwalk,
1415 	pccardstat,
1416 	pccardopen,
1417 	devcreate,
1418 	pccardclose,
1419 	pccardread,
1420 	devbread,
1421 	pccardwrite,
1422 	devbwrite,
1423 	devremove,
1424 	devwstat,
1425 };
1426 
1427 static PCMmap *
isamap(Cardbus * cb,ulong offset,int len,int attr)1428 isamap(Cardbus *cb, ulong offset, int len, int attr)
1429 {
1430 	uchar we, bit;
1431 	PCMmap *m, *nm;
1432 	Pcminfo *pi;
1433 	int i;
1434 	ulong e;
1435 
1436 	pi = &cb->linfo;
1437 
1438 	/* convert offset to granularity */
1439 	if(len <= 0)
1440 		len = 1;
1441 	e = ROUND(offset+len, Mgran);
1442 	offset &= Mmask;
1443 	len = e - offset;
1444 
1445 	/* look for a map that covers the right area */
1446 	we = rdreg(cb, Rwe);
1447 	bit = 1;
1448 	nm = 0;
1449 	for(m = pi->mmap; m < &pi->mmap[nelem(pi->mmap)]; m++){
1450 		if((we & bit))
1451 		if(m->attr == attr)
1452 		if(offset >= m->ca && e <= m->cea){
1453 
1454 			m->ref++;
1455 			return m;
1456 		}
1457 		bit <<= 1;
1458 		if(nm == 0 && m->ref == 0)
1459 			nm = m;
1460 	}
1461 	m = nm;
1462 	if(m == 0)
1463 		return 0;
1464 
1465 	/* if isa space isn't big enough, free it and get more */
1466 	if(m->len < len){
1467 		if(m->isa){
1468 			umbfree(m->isa, m->len);
1469 			m->len = 0;
1470 		}
1471 		m->isa = PADDR(umbmalloc(0, len, Mgran));
1472 		if(m->isa == 0){
1473 			print("isamap: out of isa space\n");
1474 			return 0;
1475 		}
1476 		m->len = len;
1477 	}
1478 
1479 	/* set up new map */
1480 	m->ca = offset;
1481 	m->cea = m->ca + m->len;
1482 	m->attr = attr;
1483 	i = m - pi->mmap;
1484 	bit = 1<<i;
1485 	wrreg(cb, Rwe, we & ~bit);		/* disable map before changing it */
1486 	wrreg(cb, MAP(i, Mbtmlo), m->isa>>Mshift);
1487 	wrreg(cb, MAP(i, Mbtmhi), (m->isa>>(Mshift+8)) | F16bit);
1488 	wrreg(cb, MAP(i, Mtoplo), (m->isa+m->len-1)>>Mshift);
1489 	wrreg(cb, MAP(i, Mtophi), ((m->isa+m->len-1)>>(Mshift+8)));
1490 	offset -= m->isa;
1491 	offset &= (1<<25)-1;
1492 	offset >>= Mshift;
1493 	wrreg(cb, MAP(i, Mofflo), offset);
1494 	wrreg(cb, MAP(i, Moffhi), (offset>>8) | (attr ? Fregactive : 0));
1495 	wrreg(cb, Rwe, we | bit);		/* enable map */
1496 	m->ref = 1;
1497 
1498 	return m;
1499 }
1500 
1501 static void
isaunmap(PCMmap * m)1502 isaunmap(PCMmap* m)
1503 {
1504 	m->ref--;
1505 }
1506 
1507 /*
1508  *  reading and writing card registers
1509  */
1510 static uchar
rdreg(Cardbus * cb,int index)1511 rdreg(Cardbus *cb, int index)
1512 {
1513 	outb(cb->lindex, cb->lbase + index);
1514 	return inb(cb->ldata);
1515 }
1516 
1517 static void
wrreg(Cardbus * cb,int index,uchar val)1518 wrreg(Cardbus *cb, int index, uchar val)
1519 {
1520 	outb(cb->lindex, cb->lbase + index);
1521 	outb(cb->ldata, val);
1522 }
1523 
1524 static int
readc(Cisdat * cis,uchar * x)1525 readc(Cisdat *cis, uchar *x)
1526 {
1527 	if(cis->cispos >= cis->cislen)
1528 		return 0;
1529 	*x = cis->cisbase[cis->cisskip*cis->cispos];
1530 	cis->cispos++;
1531 	return 1;
1532 }
1533 
1534 static ulong
getlong(Cisdat * cis,int size)1535 getlong(Cisdat *cis, int size)
1536 {
1537 	uchar c;
1538 	int i;
1539 	ulong x;
1540 
1541 	x = 0;
1542 	for(i = 0; i < size; i++){
1543 		if(readc(cis, &c) != 1)
1544 			break;
1545 		x |= c<<(i*8);
1546 	}
1547 	return x;
1548 }
1549 
1550 static void
tcfig(Cardbus * cb,Cisdat * cis,int)1551 tcfig(Cardbus *cb, Cisdat *cis, int )
1552 {
1553 	uchar size, rasize, rmsize;
1554 	uchar last;
1555 	Pcminfo *pi;
1556 
1557 	if(readc(cis, &size) != 1)
1558 		return;
1559 	rasize = (size&0x3) + 1;
1560 	rmsize = ((size>>2)&0xf) + 1;
1561 	if(readc(cis, &last) != 1)
1562 		return;
1563 
1564 	pi = &cb->linfo;
1565 	pi->conf_addr = getlong(cis, rasize);
1566 	pi->conf_present = getlong(cis, rmsize);
1567 }
1568 
1569 static void
tvers1(Cardbus * cb,Cisdat * cis,int)1570 tvers1(Cardbus *cb, Cisdat *cis, int )
1571 {
1572 	uchar c, major, minor, last;
1573 	int  i;
1574 	Pcminfo *pi;
1575 
1576 	pi = &cb->linfo;
1577 	if(readc(cis, &major) != 1)
1578 		return;
1579 	if(readc(cis, &minor) != 1)
1580 		return;
1581 	last = 0;
1582 	for(i = 0; i < sizeof(pi->verstr) - 1; i++){
1583 		if(readc(cis, &c) != 1)
1584 			return;
1585 		if(c == 0)
1586 			c = ';';
1587 		if(c == '\n')
1588 			c = ';';
1589 		if(c == 0xff)
1590 			break;
1591 		if(c == ';' && last == ';')
1592 			continue;
1593 		pi->verstr[i] = c;
1594 		last = c;
1595 	}
1596 	pi->verstr[i] = 0;
1597 }
1598 
1599 static ulong
microvolt(Cisdat * cis)1600 microvolt(Cisdat *cis)
1601 {
1602 	uchar c;
1603 	ulong microvolts;
1604 	ulong exp;
1605 
1606 	if(readc(cis, &c) != 1)
1607 		return 0;
1608 	exp = exponent[c&0x7];
1609 	microvolts = vmant[(c>>3)&0xf]*exp;
1610 	while(c & 0x80){
1611 		if(readc(cis, &c) != 1)
1612 			return 0;
1613 		switch(c){
1614 		case 0x7d:
1615 			break;		/* high impedence when sleeping */
1616 		case 0x7e:
1617 		case 0x7f:
1618 			microvolts = 0;	/* no connection */
1619 			break;
1620 		default:
1621 			exp /= 10;
1622 			microvolts += exp*(c&0x7f);
1623 		}
1624 	}
1625 	return microvolts;
1626 }
1627 
1628 static ulong
nanoamps(Cisdat * cis)1629 nanoamps(Cisdat *cis)
1630 {
1631 	uchar c;
1632 	ulong nanoamps;
1633 
1634 	if(readc(cis, &c) != 1)
1635 		return 0;
1636 	nanoamps = exponent[c&0x7]*vmant[(c>>3)&0xf];
1637 	while(c & 0x80){
1638 		if(readc(cis, &c) != 1)
1639 			return 0;
1640 		if(c == 0x7d || c == 0x7e || c == 0x7f)
1641 			nanoamps = 0;
1642 	}
1643 	return nanoamps;
1644 }
1645 
1646 /*
1647  * only nominal voltage (feature 1) is important for config,
1648  * other features must read card to stay in sync.
1649  */
1650 static ulong
power(Cisdat * cis)1651 power(Cisdat *cis)
1652 {
1653 	uchar feature;
1654 	ulong mv;
1655 
1656 	mv = 0;
1657 	if(readc(cis, &feature) != 1)
1658 		return 0;
1659 	if(feature & 1)
1660 		mv = microvolt(cis);
1661 	if(feature & 2)
1662 		microvolt(cis);
1663 	if(feature & 4)
1664 		microvolt(cis);
1665 	if(feature & 8)
1666 		nanoamps(cis);
1667 	if(feature & 0x10)
1668 		nanoamps(cis);
1669 	if(feature & 0x20)
1670 		nanoamps(cis);
1671 	if(feature & 0x40)
1672 		nanoamps(cis);
1673 	return mv/1000000;
1674 }
1675 
1676 static ulong
ttiming(Cisdat * cis,int scale)1677 ttiming(Cisdat *cis, int scale)
1678 {
1679 	uchar unscaled;
1680 	ulong nanosecs;
1681 
1682 	if(readc(cis, &unscaled) != 1)
1683 		return 0;
1684 	nanosecs = (mantissa[(unscaled>>3)&0xf]*exponent[unscaled&7])/10;
1685 	nanosecs = nanosecs * exponent[scale];
1686 	return nanosecs;
1687 }
1688 
1689 static void
timing(Cisdat * cis,PCMconftab * ct)1690 timing(Cisdat *cis, PCMconftab *ct)
1691 {
1692 	uchar c, i;
1693 
1694 	if(readc(cis, &c) != 1)
1695 		return;
1696 	i = c&0x3;
1697 	if(i != 3)
1698 		ct->maxwait = ttiming(cis, i);		/* max wait */
1699 	i = (c>>2)&0x7;
1700 	if(i != 7)
1701 		ct->readywait = ttiming(cis, i);	/* max ready/busy wait */
1702 	i = (c>>5)&0x7;
1703 	if(i != 7)
1704 		ct->otherwait = ttiming(cis, i);	/* reserved wait */
1705 }
1706 
1707 static void
iospaces(Cisdat * cis,PCMconftab * ct)1708 iospaces(Cisdat *cis, PCMconftab *ct)
1709 {
1710 	uchar c;
1711 	int i, nio;
1712 
1713 	ct->nio = 0;
1714 	if(readc(cis, &c) != 1)
1715 		return;
1716 
1717 	ct->bit16 = ((c>>5)&3) >= 2;
1718 	if(!(c & 0x80)){
1719 		ct->io[0].start = 0;
1720 		ct->io[0].len = 1<<(c&0x1f);
1721 		ct->nio = 1;
1722 		return;
1723 	}
1724 
1725 	if(readc(cis, &c) != 1)
1726 		return;
1727 
1728 	/*
1729 	 * For each of the range descriptions read the
1730 	 * start address and the length (value is length-1).
1731 	 */
1732 	nio = (c&0xf)+1;
1733 	for(i = 0; i < nio; i++){
1734 		ct->io[i].start = getlong(cis, (c>>4)&0x3);
1735 		ct->io[i].len = getlong(cis, (c>>6)&0x3)+1;
1736 	}
1737 	ct->nio = nio;
1738 }
1739 
1740 static void
irq(Cisdat * cis,PCMconftab * ct)1741 irq(Cisdat *cis, PCMconftab *ct)
1742 {
1743 	uchar c;
1744 
1745 	if(readc(cis, &c) != 1)
1746 		return;
1747 	ct->irqtype = c & 0xe0;
1748 	if(c & 0x10)
1749 		ct->irqs = getlong(cis, 2);
1750 	else
1751 		ct->irqs = 1<<(c&0xf);
1752 	ct->irqs &= 0xDEB8;		/* levels available to card */
1753 }
1754 
1755 static void
memspace(Cisdat * cis,int asize,int lsize,int host)1756 memspace(Cisdat *cis, int asize, int lsize, int host)
1757 {
1758 	ulong haddress, address, len;
1759 
1760 	len = getlong(cis, lsize)*256;
1761 	address = getlong(cis, asize)*256;
1762 	USED(len, address);
1763 	if(host){
1764 		haddress = getlong(cis, asize)*256;
1765 		USED(haddress);
1766 	}
1767 }
1768 
1769 static void
tentry(Cardbus * cb,Cisdat * cis,int)1770 tentry(Cardbus *cb, Cisdat *cis, int )
1771 {
1772 	uchar c, i, feature;
1773 	PCMconftab *ct;
1774 	Pcminfo *pi;
1775 
1776 	pi = &cb->linfo;
1777 	if(pi->nctab >= nelem(pi->ctab))
1778 		return;
1779 	if(readc(cis, &c) != 1)
1780 		return;
1781 	ct = &pi->ctab[pi->nctab++];
1782 
1783 	/* copy from last default config */
1784 	if(pi->defctab)
1785 		*ct = *pi->defctab;
1786 
1787 	ct->index = c & 0x3f;
1788 
1789 	/* is this the new default? */
1790 	if(c & 0x40)
1791 		pi->defctab = ct;
1792 
1793 	/* memory wait specified? */
1794 	if(c & 0x80){
1795 		if(readc(cis, &i) != 1)
1796 			return;
1797 		if(i&0x80)
1798 			ct->memwait = 1;
1799 	}
1800 
1801 	if(readc(cis, &feature) != 1)
1802 		return;
1803 	switch(feature&0x3){
1804 	case 1:
1805 		ct->vpp1 = ct->vpp2 = power(cis);
1806 		break;
1807 	case 2:
1808 		power(cis);
1809 		ct->vpp1 = ct->vpp2 = power(cis);
1810 		break;
1811 	case 3:
1812 		power(cis);
1813 		ct->vpp1 = power(cis);
1814 		ct->vpp2 = power(cis);
1815 		break;
1816 	default:
1817 		break;
1818 	}
1819 	if(feature&0x4)
1820 		timing(cis, ct);
1821 	if(feature&0x8)
1822 		iospaces(cis, ct);
1823 	if(feature&0x10)
1824 		irq(cis, ct);
1825 	switch((feature>>5)&0x3){
1826 	case 1:
1827 		memspace(cis, 0, 2, 0);
1828 		break;
1829 	case 2:
1830 		memspace(cis, 2, 2, 0);
1831 		break;
1832 	case 3:
1833 		if(readc(cis, &c) != 1)
1834 			return;
1835 		for(i = 0; i <= (c&0x7); i++)
1836 			memspace(cis, (c>>5)&0x3, (c>>3)&0x3, c&0x80);
1837 		break;
1838 	}
1839 }
1840 
1841 static void
i82365probe(Cardbus * cb,int lindex,int ldata)1842 i82365probe(Cardbus *cb, int lindex, int ldata)
1843 {
1844 	uchar c, id;
1845 	int dev = 0;	/* According to the Ricoh spec 00->3F _and_ 80->BF seem
1846 				     to be the same socket A (ditto for B). */
1847 
1848 	outb(lindex, Rid + (dev<<7));
1849 	id = inb(ldata);
1850 	if((id & 0xf0) != 0x80)
1851 		return;		/* not a memory & I/O card */
1852 	if((id & 0x0f) == 0x00)
1853 		return;		/* no revision number, not possible */
1854 
1855 	cb->lindex = lindex;
1856 	cb->ldata = ldata;
1857 	cb->ltype = Ti82365;
1858 	cb->lbase = (int)(cb - cbslots) * 0x40;
1859 
1860 	switch(id){
1861 	case 0x82:
1862 	case 0x83:
1863 	case 0x84:
1864 		/* could be a cirrus */
1865 		outb(cb->lindex, Rchipinfo + (dev<<7));
1866 		outb(cb->ldata, 0);
1867 		c = inb(cb->ldata);
1868 		if((c & 0xc0) != 0xc0)
1869 			break;
1870 		c = inb(cb->ldata);
1871 		if((c & 0xc0) != 0x00)
1872 			break;
1873 		if(c & 0x20){
1874 			cb->ltype = Tpd6720;
1875 		} else {
1876 			cb->ltype = Tpd6710;
1877 		}
1878 
1879 		/* low power mode */
1880 		outb(cb->lindex, Rmisc2 + (dev<<7));
1881 		c = inb(cb->ldata);
1882 		outb(cb->ldata, c & ~Flowpow);
1883 		break;
1884 		break;
1885 	}
1886 
1887 	/* if it's not a Cirrus, it could be a Vadem... */
1888 	if(cb->ltype == Ti82365){
1889 		/* unlock the Vadem extended regs */
1890 		outb(cb->lindex, 0x0E + (dev<<7));
1891 		outb(cb->lindex, 0x37 + (dev<<7));
1892 
1893 		/* make the id register show the Vadem id */
1894 		outb(cb->lindex, 0x3A + (dev<<7));
1895 		c = inb(cb->ldata);
1896 		outb(cb->ldata, c|0xC0);
1897 		outb(cb->lindex, Rid + (dev<<7));
1898 		c = inb(cb->ldata);
1899 		if(c & 0x08)
1900 			cb->ltype = Tvg46x;
1901 
1902 		/* go back to Intel compatible id */
1903 		outb(cb->lindex, 0x3A + (dev<<7));
1904 		c = inb(cb->ldata);
1905 		outb(cb->ldata, c & ~0xC0);
1906 	}
1907 }
1908 
1909 static int
vcode(int volt)1910 vcode(int volt)
1911 {
1912 	switch(volt){
1913 	case 5:
1914 		return 1;
1915 	case 12:
1916 		return 2;
1917 	default:
1918 		return 0;
1919 	}
1920 }
1921