Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
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
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
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
444
eventoccured(void)
445
{
446
	return nevents > 0;
447
}
448
 
449
static 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
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
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
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
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
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
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
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
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
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*
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
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*
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
1240
pccardstat(Chan *c, uchar *db, int n)
1241
{
1242
	return devstat(c, db, n, 0, 0, pccardgen);
1243
}
1244
 
1245
static void
1246
increfp(Cardbus *cb)
1247
{
1248
	lock(&cb->refslock);
1249
	cb->refs++;
1250
	unlock(&cb->refslock);
1251
}
1252
 
1253
static void
1254
decrefp(Cardbus *cb)
1255
{
1256
	lock(&cb->refslock);
1257
	cb->refs--;
1258
	unlock(&cb->refslock);
1259
}
1260
 
1261
static Chan*
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
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
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
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 *
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
1502
isaunmap(PCMmap* m)
1503
{
1504
	m->ref--;
1505
}
1506
 
1507
/*
1508
 *  reading and writing card registers
1509
 */
1510
static uchar
1511
rdreg(Cardbus *cb, int index)
1512
{
1513
	outb(cb->lindex, cb->lbase + index);
1514
	return inb(cb->ldata);
1515
}
1516
 
1517
static void
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
}