xref: /plan9-contrib/sys/src/9/loongson/2f/pci.c (revision a81c3ea0c7f009a3088ab7fe55ea9013d9d77a74)
1 /*
2  *	PCI support code.
3  */
4 
5 #include "u.h"
6 #include "../port/lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "io.h"
11 
12 typedef struct Pci Pci;
13 
14 struct Pci {
15 	ulong	id;
16 	ulong	cs;
17 	ulong	revclass;
18 	ulong	misc;	/* cache line size, latency timer, header type, bist */
19 	ulong	base[6];	/* base addr regs */
20 	ulong	unused[5];
21 	ulong	intr;
22 	ulong	mask[6];
23 	ulong	trans[6];
24 };
25 
26 enum {
27 	/* cs bits */
28 	CIoEn		= (1<<0),
29 	CMemEn		= (1<<1),
30 	CMasEn		= (1<<2),
31 	CSpcEn		= (1<<4),
32 	CParEn		= (1<<6),
33 	CSErrEn		= (1<<8),
34 
35 	SMasTgtAb	= (1<<24),	/* master target abort */
36 	SMasAb		= (1<<25),	/* master abort */
37 };
38 
39 enum {
40 	MaxFNO		= 7,
41 	MaxUBN		= 255,
42 };
43 
44 enum
45 {					/* command register */
46 	IOen		= (1<<0),
47 	MEMen		= (1<<1),
48 	MASen		= (1<<2),
49 	MemWrInv	= (1<<4),
50 	PErrEn		= (1<<6),
51 	SErrEn		= (1<<8),
52 };
53 
54 static Lock pcicfglock;
55 static Lock pcicfginitlock;
56 static int pcicfgmode = -1;
57 static int pcimaxbno = 0;
58 static int pcimaxdno;
59 static Pcidev *pciroot;
60 static Pcidev *pcilist;
61 static Pcidev *pcitail;
62 static Pci *pci = (Pci*)PCICFG;
63 
64 static int pcicfgrw8(int, int, int, int);
65 static int pcicfgrw16(int, int, int, int);
66 static int pcicfgrw32(int, int, int, int);
67 
68 static char* bustypes[] = {
69 	"CBUSI",
70 	"CBUSII",
71 	"EISA",
72 	"FUTURE",
73 	"INTERN",
74 	"ISA",
75 	"MBI",
76 	"MBII",
77 	"MCA",
78 	"MPI",
79 	"MPSA",
80 	"NUBUS",
81 	"PCI",
82 	"PCMCIA",
83 	"TC",
84 	"VL",
85 	"VME",
86 	"XPRESS",
87 };
88 
89 static int
tbdffmt(Fmt * fmt)90 tbdffmt(Fmt* fmt)
91 {
92 	char *p;
93 	int l, r;
94 	uint type, tbdf;
95 
96 	if((p = malloc(READSTR)) == nil)
97 		return fmtstrcpy(fmt, "(tbdfconv)");
98 
99 	switch(fmt->r){
100 	case 'T':
101 		tbdf = va_arg(fmt->args, int);
102 		if(tbdf == BUSUNKNOWN)
103 			snprint(p, READSTR, "unknown");
104 		else{
105 			type = BUSTYPE(tbdf);
106 			if(type < nelem(bustypes))
107 				l = snprint(p, READSTR, bustypes[type]);
108 			else
109 				l = snprint(p, READSTR, "%d", type);
110 			snprint(p+l, READSTR-l, ".%d.%d.%d",
111 				BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
112 		}
113 		break;
114 
115 	default:
116 		snprint(p, READSTR, "(tbdfconv)");
117 		break;
118 	}
119 	r = fmtstrcpy(fmt, p);
120 	free(p);
121 
122 	return r;
123 }
124 
125 ulong
pcibarsize(Pcidev * p,int rno)126 pcibarsize(Pcidev *p, int rno)
127 {
128 	ulong v, size;
129 
130 	v = pcicfgrw32(p->tbdf, rno, 0, 1);
131 	pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
132 	size = pcicfgrw32(p->tbdf, rno, 0, 1);
133 	if(v & 1)
134 		size |= 0xFFFF0000;
135 	pcicfgrw32(p->tbdf, rno, v, 0);
136 
137 	return -(size & ~0x0F);
138 }
139 
140 static int
pcilscan(int bno,Pcidev ** list)141 pcilscan(int bno, Pcidev** list)
142 {
143 	Pcidev *p, *head, *tail;
144 	int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
145 
146 	maxubn = bno;
147 	head = nil;
148 	tail = nil;
149 	/* dno from 5 due to its address mode */
150 	for(dno = 5; dno <= pcimaxdno; dno++){
151 		maxfno = 0;
152 		for(fno = 0; fno <= maxfno; fno++){
153 			/*
154 			 * For this possible device, form the
155 			 * bus+device+function triplet needed to address it
156 			 * and try to read the vendor and device ID.
157 			 * If successful, allocate a device struct and
158 			 * start to fill it in with some useful information
159 			 * from the device's configuration space.
160 			 */
161 			tbdf = MKBUS(BusPCI, bno, dno, fno);
162 			l = pcicfgrw32(tbdf, PciVID, 0, 1);
163 			if(l == 0xFFFFFFFF || l == 0)
164 				continue;
165 			p = malloc(sizeof(*p));
166 			if(p == nil)
167 				panic("pcilscan: no memory");
168 			p->tbdf = tbdf;
169 			p->vid = l;
170 			p->did = l>>16;
171 
172 			if(pcilist != nil)
173 				pcitail->list = p;
174 			else
175 				pcilist = p;
176 			pcitail = p;
177 
178 			p->pcr = pcicfgr16(p, PciPCR);
179 			p->rid = pcicfgr8(p, PciRID);
180 			p->ccrp = pcicfgr8(p, PciCCRp);
181 			p->ccru = pcicfgr8(p, PciCCRu);
182 			p->ccrb = pcicfgr8(p, PciCCRb);
183 			p->cls = pcicfgr8(p, PciCLS);
184 			p->ltr = pcicfgr8(p, PciLTR);
185 
186 			p->intl = pcicfgr8(p, PciINTL);
187 			p->intp = pcicfgr8(p, PciINTP);
188 
189 			/*
190 			 * If the device is a multi-function device adjust the
191 			 * loop count so all possible functions are checked.
192 			 */
193 			hdt = pcicfgr8(p, PciHDT);
194 			if(hdt & 0x80)
195 				maxfno = MaxFNO;
196 
197 			/*
198 			 * If appropriate, read the base address registers
199 			 * and work out the sizes.
200 			 */
201 			switch(p->ccrb) {
202 			case 0x03:		/* display controller */
203 				/* fall through */
204 			case 0x01:		/* mass storage controller */
205 			case 0x02:		/* network controller */
206 			case 0x04:		/* multimedia device */
207 			case 0x07:		/* simple comm. controllers */
208 			case 0x08:		/* base system peripherals */
209 			case 0x09:		/* input devices */
210 			case 0x0A:		/* docking stations */
211 			case 0x0B:		/* processors */
212 			case 0x0C:		/* serial bus controllers */
213 				if((hdt & 0x7F) != 0)
214 					break;
215 				rno = PciBAR0 - 4;
216 				for(i = 0; i < nelem(p->mem); i++) {
217 					rno += 4;
218 					p->mem[i].bar = pcicfgr32(p, rno);
219 					p->mem[i].size = pcibarsize(p, rno);
220 				}
221 				break;
222 
223 			case 0x00:
224 			case 0x05:		/* memory controller */
225 			case 0x06:		/* bridge device */
226 			default:
227 				break;
228 			}
229 
230 			if(head != nil)
231 				tail->link = p;
232 			else
233 				head = p;
234 			tail = p;
235 		}
236 	}
237 
238 	*list = head;
239 	for(p = head; p != nil; p = p->link){
240 		/*
241 		 * Find PCI-PCI bridges and recursively descend the tree.
242 		 */
243 		if(p->ccrb != 0x06 || p->ccru != 0x04)
244 			continue;
245 
246 		/*
247 		 * If the secondary or subordinate bus number is not
248 		 * initialised try to do what the PCI BIOS should have
249 		 * done and fill in the numbers as the tree is descended.
250 		 * On the way down the subordinate bus number is set to
251 		 * the maximum as it's not known how many buses are behind
252 		 * this one; the final value is set on the way back up.
253 		 */
254 		sbn = pcicfgr8(p, PciSBN);
255 		ubn = pcicfgr8(p, PciUBN);
256 
257 		if(sbn == 0 || ubn == 0) {
258 			sbn = maxubn+1;
259 			/*
260 			 * Make sure memory, I/O and master enables are
261 			 * off, set the primary, secondary and subordinate
262 			 * bus numbers and clear the secondary status before
263 			 * attempting to scan the secondary bus.
264 			 *
265 			 * Initialisation of the bridge should be done here.
266 			 */
267 			pcicfgw32(p, PciPCR, 0xFFFF0000);
268 			l = (MaxUBN<<16)|(sbn<<8)|bno;
269 			pcicfgw32(p, PciPBN, l);
270 			pcicfgw16(p, PciSPSR, 0xFFFF);
271 			maxubn = pcilscan(sbn, &p->bridge);
272 			l = (maxubn<<16)|(sbn<<8)|bno;
273 
274 			pcicfgw32(p, PciPBN, l);
275 		}
276 		else {
277 			if(ubn > maxubn)
278 				maxubn = ubn;
279 			pcilscan(sbn, &p->bridge);
280 		}
281 	}
282 
283 	return maxubn;
284 }
285 
286 static void
pcicfginit(void)287 pcicfginit(void)
288 {
289 	char *p;
290 	int n, bno;
291 	Pcidev **list;
292 
293 	lock(&pcicfginitlock);
294 	if(pcicfgmode != -1) {
295 		unlock(&pcicfginitlock);
296 		return;
297 	}
298 
299 	pcicfgmode = 1;
300 	pcimaxdno = 19;
301 
302 	fmtinstall('T', tbdffmt);
303 
304 	if(p = getconf("*pcimaxbno")){
305 		n = strtoul(p, 0, 0);
306 		if(n < pcimaxbno)
307 			pcimaxbno = n;
308 	}
309 	if(p = getconf("*pcimaxdno")){
310 		n = strtoul(p, 0, 0);
311 		if(n < pcimaxdno)
312 			pcimaxdno = n;
313 	}
314 
315 	list = &pciroot;
316 	for(bno = 0; bno <= pcimaxbno; bno++){
317 		bno = pcilscan(bno, list);
318 		while(*list)
319 			list = &(*list)->link;
320 	}
321 	unlock(&pcicfginitlock);
322 }
323 
324 /* map the devince's cfg space and calculate the address */
325 static void*
pcidevcfgaddr(int tbdf,int rno)326 pcidevcfgaddr(int tbdf, int rno)
327 {
328 	ulong addr;
329 	ulong b, d, f, type;
330 
331 	b = BUSBNO(tbdf);
332 	d = BUSDNO(tbdf);
333 	f = BUSFNO(tbdf);
334     if(b == 0) {
335         /* Type 0 configuration on onboard PCI bus */
336         addr = (1<<(d+11))|(f<<8)|rno;
337         type = 0x00000;
338     } else {
339         /* Type 1 configuration on offboard PCI bus */
340         addr = (b<<16)|(d<<11)|(f<<8)|rno;
341         type = 0x10000;
342     }
343 
344     /* clear aborts */
345     pci->cs |= SMasAb | SMasTgtAb;
346 
347 	/* config map cfg reg to map the device's cfg space */
348     *Pcimapcfg = (addr>>16)|type;
349 
350 	return (void*)(PCIDEVCFG+(addr&0xffff));
351 }
352 
353 static int
pcicfgrw8(int tbdf,int rno,int data,int read)354 pcicfgrw8(int tbdf, int rno, int data, int read)
355 {
356 	int x;
357 	void *addr;
358 
359 	if(pcicfgmode == -1)
360 		pcicfginit();
361 
362 	x = -1;
363 	if(BUSDNO(tbdf) > pcimaxdno)
364 		return x;
365 
366 	lock(&pcicfglock);
367 	addr = pcidevcfgaddr(tbdf, rno);
368 	if(read)
369 		x = *(uchar*)addr;
370 	else
371 		*(uchar*)addr = data;
372 	unlock(&pcicfglock);
373 
374 	return x;
375 }
376 
377 int
pcicfgr8(Pcidev * pcidev,int rno)378 pcicfgr8(Pcidev* pcidev, int rno)
379 {
380 	return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
381 }
382 
383 void
pcicfgw8(Pcidev * pcidev,int rno,int data)384 pcicfgw8(Pcidev* pcidev, int rno, int data)
385 {
386 	pcicfgrw8(pcidev->tbdf, rno, data, 0);
387 }
388 
389 static int
pcicfgrw16(int tbdf,int rno,int data,int read)390 pcicfgrw16(int tbdf, int rno, int data, int read)
391 {
392 	int x;
393 	void *addr;
394 
395 	if(pcicfgmode == -1)
396 		pcicfginit();
397 
398 	x = -1;
399 	if(BUSDNO(tbdf) > pcimaxdno)
400 		return x;
401 
402 	lock(&pcicfglock);
403 	addr = pcidevcfgaddr(tbdf, rno);
404 	if(read)
405 		x = *(ushort*)addr;
406 	else
407 		*(ushort*)addr = data;
408 	unlock(&pcicfglock);
409 
410 	return x;
411 }
412 
413 int
pcicfgr16(Pcidev * pcidev,int rno)414 pcicfgr16(Pcidev* pcidev, int rno)
415 {
416 	return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
417 }
418 
419 void
pcicfgw16(Pcidev * pcidev,int rno,int data)420 pcicfgw16(Pcidev* pcidev, int rno, int data)
421 {
422 	pcicfgrw16(pcidev->tbdf, rno, data, 0);
423 }
424 
425 static int
pcicfgrw32(int tbdf,int rno,int data,int read)426 pcicfgrw32(int tbdf, int rno, int data, int read)
427 {
428 	int x;
429 	void *addr;
430 
431 	if(pcicfgmode == -1)
432 		pcicfginit();
433 
434 	x = -1;
435 	if(BUSDNO(tbdf) > pcimaxdno)
436 		return x;
437 
438 	lock(&pcicfglock);
439 	addr = pcidevcfgaddr(tbdf, rno);
440 	if(read)
441 		x = *(ulong*)addr;
442 	else
443 		*(ulong*)addr = data;
444 	unlock(&pcicfglock);
445 
446 	return x;
447 }
448 
449 int
pcicfgr32(Pcidev * pcidev,int rno)450 pcicfgr32(Pcidev* pcidev, int rno)
451 {
452 	return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
453 }
454 
455 void
pcicfgw32(Pcidev * pcidev,int rno,int data)456 pcicfgw32(Pcidev* pcidev, int rno, int data)
457 {
458 	pcicfgrw32(pcidev->tbdf, rno, data, 0);
459 }
460 
461 Pcidev*
pcimatch(Pcidev * prev,int vid,int did)462 pcimatch(Pcidev* prev, int vid, int did)
463 {
464 	if(pcicfgmode == -1)
465 		pcicfginit();
466 
467 	if(prev == nil)
468 		prev = pcilist;
469 	else
470 		prev = prev->list;
471 
472 	while(prev != nil){
473 		if((vid == 0 || prev->vid == vid)
474 		&& (did == 0 || prev->did == did))
475 			break;
476 		prev = prev->list;
477 	}
478 	return prev;
479 }
480 
481 Pcidev*
pcimatchtbdf(int tbdf)482 pcimatchtbdf(int tbdf)
483 {
484 	Pcidev *pcidev;
485 
486 	if(pcicfgmode == -1)
487 		pcicfginit();
488 
489 	for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
490 		if(pcidev->tbdf == tbdf)
491 			break;
492 	}
493 	return pcidev;
494 }
495 
496 void
pcireset(void)497 pcireset(void)
498 {
499 	Pcidev *p;
500 
501 	if(pcicfgmode == -1)
502 		pcicfginit();
503 
504 	for(p = pcilist; p != nil; p = p->list) {
505 		/* don't mess with the bridges */
506 		if(p->ccrb == 0x06)
507 			continue;
508 		pciclrbme(p);
509 	}
510 }
511 
512 void
pcisetioe(Pcidev * p)513 pcisetioe(Pcidev* p)
514 {
515 	p->pcr |= IOen;
516 	pcicfgw16(p, PciPCR, p->pcr);
517 }
518 
519 void
pciclrioe(Pcidev * p)520 pciclrioe(Pcidev* p)
521 {
522 	p->pcr &= ~IOen;
523 	pcicfgw16(p, PciPCR, p->pcr);
524 }
525 
526 void
pcisetbme(Pcidev * p)527 pcisetbme(Pcidev* p)
528 {
529 	p->pcr |= MASen;
530 	pcicfgw16(p, PciPCR, p->pcr);
531 }
532 
533 void
pciclrbme(Pcidev * p)534 pciclrbme(Pcidev* p)
535 {
536 	p->pcr &= ~MASen;
537 	pcicfgw16(p, PciPCR, p->pcr);
538 }
539 
540 void
pcisetmwi(Pcidev * p)541 pcisetmwi(Pcidev* p)
542 {
543 	p->pcr |= MemWrInv;
544 	pcicfgw16(p, PciPCR, p->pcr);
545 }
546 
547 void
pciclrmwi(Pcidev * p)548 pciclrmwi(Pcidev* p)
549 {
550 	p->pcr &= ~MemWrInv;
551 	pcicfgw16(p, PciPCR, p->pcr);
552 }
553 
554 static int
pcigetpmrb(Pcidev * p)555 pcigetpmrb(Pcidev* p)
556 {
557 	int ptr;
558 
559 	if(p->pmrb != 0)
560 		return p->pmrb;
561 	p->pmrb = -1;
562 
563 	/*
564 	 * If there are no extended capabilities implemented,
565 	 * (bit 4 in the status register) assume there's no standard
566 	 * power management method.
567 	 * Find the capabilities pointer based on PCI header type.
568 	 */
569 	if(!(pcicfgr16(p, PciPSR) & 0x0010))
570 		return -1;
571 	switch(pcicfgr8(p, PciHDT)){
572 	default:
573 		return -1;
574 	case 0:					/* all other */
575 	case 1:					/* PCI to PCI bridge */
576 		ptr = 0x34;
577 		break;
578 	case 2:					/* CardBus bridge */
579 		ptr = 0x14;
580 		break;
581 	}
582 	ptr = pcicfgr32(p, ptr);
583 
584 	while(ptr != 0){
585 		/*
586 		 * Check for validity.
587 		 * Can't be in standard header and must be double
588 		 * word aligned.
589 		 */
590 		if(ptr < 0x40 || (ptr & ~0xFC))
591 			return -1;
592 		if(pcicfgr8(p, ptr) == 0x01){
593 			p->pmrb = ptr;
594 			return ptr;
595 		}
596 
597 		ptr = pcicfgr8(p, ptr+1);
598 	}
599 
600 	return -1;
601 }
602 
603 int
pcigetpms(Pcidev * p)604 pcigetpms(Pcidev* p)
605 {
606 	int pmcsr, ptr;
607 
608 	if((ptr = pcigetpmrb(p)) == -1)
609 		return -1;
610 
611 	/*
612 	 * Power Management Register Block:
613 	 *  offset 0:	Capability ID
614 	 *	   1:	next item pointer
615 	 *	   2:	capabilities
616 	 *	   4:	control/status
617 	 *	   6:	bridge support extensions
618 	 *	   7:	data
619 	 */
620 	pmcsr = pcicfgr16(p, ptr+4);
621 
622 	return pmcsr & 0x0003;
623 }
624 
625 int
pcisetpms(Pcidev * p,int state)626 pcisetpms(Pcidev* p, int state)
627 {
628 	int ostate, pmc, pmcsr, ptr;
629 
630 	if((ptr = pcigetpmrb(p)) == -1)
631 		return -1;
632 
633 	pmc = pcicfgr16(p, ptr+2);
634 	pmcsr = pcicfgr16(p, ptr+4);
635 	ostate = pmcsr & 0x0003;
636 	pmcsr &= ~0x0003;
637 
638 	switch(state){
639 	default:
640 		return -1;
641 	case 0:
642 		break;
643 	case 1:
644 		if(!(pmc & 0x0200))
645 			return -1;
646 		break;
647 	case 2:
648 		if(!(pmc & 0x0400))
649 			return -1;
650 		break;
651 	case 3:
652 		break;
653 	}
654 	pmcsr |= state;
655 	pcicfgw16(p, ptr+4, pmcsr);
656 
657 	return ostate;
658 }
659 
660 int
pcisubirq(int tbdf)661 pcisubirq(int tbdf)
662 {
663 //	return Pciintrbase + pcicfgrw8(tbdf, PciINTP, 0, 1);
664 	USED(tbdf);
665 	return 5;	// XXX rtl8139
666 }
667