cpci_hotplug_pci.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2
1/*
2 * CompactPCI Hot Plug Driver PCI functions
3 *
4 * Copyright (C) 2002 by SOMA Networks, Inc.
5 *
6 * All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or (at
11 * your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
16 * NON INFRINGEMENT.  See the GNU General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 * Send feedback to <scottm@somanetworks.com>
24 */
25
26#include <linux/config.h>
27#include <linux/module.h>
28#include <linux/kernel.h>
29#include <linux/pci.h>
30#include <linux/proc_fs.h>
31#include "../pci.h"
32#include "pci_hotplug.h"
33#include "cpci_hotplug.h"
34
35#if !defined(MODULE)
36#define MY_NAME	"cpci_hotplug"
37#else
38#define MY_NAME	THIS_MODULE->name
39#endif
40
41extern int cpci_debug;
42
43#define dbg(format, arg...)					\
44	do {							\
45		if(cpci_debug)					\
46			printk (KERN_DEBUG "%s: " format "\n",	\
47				MY_NAME , ## arg); 		\
48	} while(0)
49#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
50#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
51#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
52
53#define ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))
54
55
56u8 cpci_get_attention_status(struct slot* slot)
57{
58	int hs_cap;
59	u16 hs_csr;
60
61	hs_cap = pci_bus_find_capability(slot->bus,
62					 slot->devfn,
63					 PCI_CAP_ID_CHSWP);
64	if(!hs_cap) {
65		return 0;
66	}
67
68	if(pci_bus_read_config_word(slot->bus,
69				     slot->devfn,
70				     hs_cap + 2,
71				     &hs_csr)) {
72		return 0;
73	}
74	return hs_csr & 0x0008 ? 1 : 0;
75}
76
77int cpci_set_attention_status(struct slot* slot, int status)
78{
79	int hs_cap;
80	u16 hs_csr;
81
82	hs_cap = pci_bus_find_capability(slot->bus,
83					 slot->devfn,
84					 PCI_CAP_ID_CHSWP);
85	if(!hs_cap) {
86		return 0;
87	}
88
89	if(pci_bus_read_config_word(slot->bus,
90				     slot->devfn,
91				     hs_cap + 2,
92				     &hs_csr)) {
93		return 0;
94	}
95	if(status) {
96		hs_csr |= HS_CSR_LOO;
97	} else {
98		hs_csr &= ~HS_CSR_LOO;
99	}
100	if(pci_bus_write_config_word(slot->bus,
101				      slot->devfn,
102				      hs_cap + 2,
103				      hs_csr)) {
104		return 0;
105	}
106	return 1;
107}
108
109u16 cpci_get_hs_csr(struct slot* slot)
110{
111	int hs_cap;
112	u16 hs_csr;
113
114	hs_cap = pci_bus_find_capability(slot->bus,
115					 slot->devfn,
116					 PCI_CAP_ID_CHSWP);
117	if(!hs_cap) {
118		return 0xFFFF;
119	}
120
121	if(pci_bus_read_config_word(slot->bus,
122				     slot->devfn,
123				     hs_cap + 2,
124				     &hs_csr)) {
125		return 0xFFFF;
126	}
127	return hs_csr;
128}
129
130#if 0
131u16 cpci_set_hs_csr(struct slot* slot, u16 hs_csr)
132{
133	int hs_cap;
134	u16 new_hs_csr;
135
136	hs_cap = pci_bus_find_capability(slot->bus,
137					 slot->devfn,
138					 PCI_CAP_ID_CHSWP);
139	if(!hs_cap) {
140		return 0xFFFF;
141	}
142
143	/* Write out the new value */
144	if(pci_bus_write_config_word(slot->bus,
145				      slot->devfn,
146				      hs_cap + 2,
147				      hs_csr)) {
148		return 0xFFFF;
149	}
150
151	/* Read back what we just wrote out */
152	if(pci_bus_read_config_word(slot->bus,
153				     slot->devfn,
154				     hs_cap + 2,
155				     &new_hs_csr)) {
156		return 0xFFFF;
157	}
158	return new_hs_csr;
159}
160#endif
161
162int cpci_check_and_clear_ins(struct slot* slot)
163{
164	int hs_cap;
165	u16 hs_csr;
166	int ins = 0;
167
168	hs_cap = pci_bus_find_capability(slot->bus,
169					 slot->devfn,
170					 PCI_CAP_ID_CHSWP);
171	if(!hs_cap) {
172		return 0;
173	}
174	if(pci_bus_read_config_word(slot->bus,
175				     slot->devfn,
176				     hs_cap + 2,
177				     &hs_csr)) {
178		return 0;
179	}
180	if(hs_csr & HS_CSR_INS) {
181		/* Clear INS (by setting it) */
182		if(pci_bus_write_config_word(slot->bus,
183					      slot->devfn,
184					      hs_cap + 2,
185					      hs_csr)) {
186			ins = 0;
187		}
188		ins = 1;
189	}
190	return ins;
191}
192
193int cpci_check_ext(struct slot* slot)
194{
195	int hs_cap;
196	u16 hs_csr;
197	int ext = 0;
198
199	hs_cap = pci_bus_find_capability(slot->bus,
200					 slot->devfn,
201					 PCI_CAP_ID_CHSWP);
202	if(!hs_cap) {
203		return 0;
204	}
205	if(pci_bus_read_config_word(slot->bus,
206				     slot->devfn,
207				     hs_cap + 2,
208				     &hs_csr)) {
209		return 0;
210	}
211	if(hs_csr & HS_CSR_EXT) {
212		ext = 1;
213	}
214	return ext;
215}
216
217int cpci_clear_ext(struct slot* slot)
218{
219	int hs_cap;
220	u16 hs_csr;
221
222	hs_cap = pci_bus_find_capability(slot->bus,
223					 slot->devfn,
224					 PCI_CAP_ID_CHSWP);
225	if(!hs_cap) {
226		return -ENODEV;
227	}
228	if(pci_bus_read_config_word(slot->bus,
229				     slot->devfn,
230				     hs_cap + 2,
231				     &hs_csr)) {
232		return -ENODEV;
233	}
234	if(hs_csr & HS_CSR_EXT) {
235		/* Clear EXT (by setting it) */
236		if(pci_bus_write_config_word(slot->bus,
237					      slot->devfn,
238					      hs_cap + 2,
239					      hs_csr)) {
240			return -ENODEV;
241		}
242	}
243	return 0;
244}
245
246int cpci_led_on(struct slot* slot)
247{
248	int hs_cap;
249	u16 hs_csr;
250
251	hs_cap = pci_bus_find_capability(slot->bus,
252					 slot->devfn,
253					 PCI_CAP_ID_CHSWP);
254	if(!hs_cap) {
255		return -ENODEV;
256	}
257	if(pci_bus_read_config_word(slot->bus,
258				     slot->devfn,
259				     hs_cap + 2,
260				     &hs_csr)) {
261		return -ENODEV;
262	}
263	if((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
264		/* Set LOO */
265		hs_csr |= HS_CSR_LOO;
266		if(pci_bus_write_config_word(slot->bus,
267					      slot->devfn,
268					      hs_cap + 2,
269					      hs_csr)) {
270			err("Could not set LOO for slot %s",
271			    slot->hotplug_slot->name);
272			return -ENODEV;
273		}
274	}
275	return 0;
276}
277
278int cpci_led_off(struct slot* slot)
279{
280	int hs_cap;
281	u16 hs_csr;
282
283	hs_cap = pci_bus_find_capability(slot->bus,
284					 slot->devfn,
285					 PCI_CAP_ID_CHSWP);
286	if(!hs_cap) {
287		return -ENODEV;
288	}
289	if(pci_bus_read_config_word(slot->bus,
290				     slot->devfn,
291				     hs_cap + 2,
292				     &hs_csr)) {
293		return -ENODEV;
294	}
295	if(hs_csr & HS_CSR_LOO) {
296		/* Clear LOO */
297		hs_csr &= ~HS_CSR_LOO;
298		if(pci_bus_write_config_word(slot->bus,
299					      slot->devfn,
300					      hs_cap + 2,
301					      hs_csr)) {
302			err("Could not clear LOO for slot %s",
303			    slot->hotplug_slot->name);
304			return -ENODEV;
305		}
306	}
307	return 0;
308}
309
310
311/*
312 * Device configuration functions
313 */
314
315static int cpci_configure_dev(struct pci_bus *bus, struct pci_dev *dev)
316{
317	u8 irq_pin;
318	int r;
319
320	dbg("%s - enter", __FUNCTION__);
321
322	/* NOTE: device already setup from prior scan */
323
324	/* FIXME: How would we know if we need to enable the expansion ROM? */
325	pci_write_config_word(dev, PCI_ROM_ADDRESS, 0x00L);
326
327	/* Assign resources */
328	dbg("assigning resources for %02x:%02x.%x",
329	    dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
330	for (r = 0; r < 6; r++) {
331		struct resource *res = dev->resource + r;
332		if(res->flags)
333			pci_assign_resource(dev, r);
334	}
335	dbg("finished assigning resources for %02x:%02x.%x",
336	    dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
337
338	/* Does this function have an interrupt at all? */
339	dbg("checking for function interrupt");
340	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &irq_pin);
341	if(irq_pin) {
342		dbg("function uses interrupt pin %d", irq_pin);
343	}
344
345	/*
346	 * Need to explicitly set irq field to 0 so that it'll get assigned
347	 * by the pcibios platform dependent code called by pci_enable_device.
348	 */
349	dev->irq = 0;
350
351	dbg("enabling device");
352	pci_enable_device(dev);	/* XXX check return */
353	dbg("now dev->irq = %d", dev->irq);
354	if(irq_pin && dev->irq) {
355		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
356	}
357
358	/* Can't use pci_insert_device at the moment, do it manually for now */
359	pci_proc_attach_device(dev);
360	dbg("notifying drivers");
361	//pci_announce_device_to_drivers(dev);
362	dbg("%s - exit", __FUNCTION__);
363	return 0;
364}
365
366static int cpci_configure_bridge(struct pci_bus* bus, struct pci_dev* dev)
367{
368	int rc;
369	struct pci_bus* child;
370	struct resource* r;
371	u8 max, n;
372	u16 command;
373
374	dbg("%s - enter", __FUNCTION__);
375
376	/* Do basic bridge initialization */
377	rc = pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40);
378	if(rc) {
379		printk(KERN_ERR "%s - write of PCI_LATENCY_TIMER failed\n", __FUNCTION__);
380	}
381	rc = pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 0x40);
382	if(rc) {
383		printk(KERN_ERR "%s - write of PCI_SEC_LATENCY_TIMER failed\n", __FUNCTION__);
384	}
385	rc = pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, L1_CACHE_BYTES / 4);
386	if(rc) {
387		printk(KERN_ERR "%s - write of PCI_CACHE_LINE_SIZE failed\n", __FUNCTION__);
388	}
389
390	/*
391	 * Set parent bridge's subordinate field so that configuration space
392	 * access will work in pci_scan_bridge and friends.
393	 */
394	max = pci_max_busnr();
395	bus->subordinate = max + 1;
396	pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, max + 1);
397
398	/* Scan behind bridge */
399	n = pci_scan_bridge(bus, dev, max, 2);
400	child = pci_find_bus(0, max + 1);
401	if (!child)
402		return -ENODEV;
403	pci_proc_attach_bus(child);
404
405	/*
406	 * Update parent bridge's subordinate field if there were more bridges
407	 * behind the bridge that was scanned.
408	 */
409	if(n > max) {
410		bus->subordinate = n;
411		pci_write_config_byte(bus->self, PCI_SUBORDINATE_BUS, n);
412	}
413
414	/*
415	 * Update the bridge resources of the bridge to accommodate devices
416	 * behind it.
417	 */
418	pci_bus_size_bridges(child);
419	pci_bus_assign_resources(child);
420
421	/* Enable resource mapping via command register */
422	command = PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE | PCI_COMMAND_PARITY | PCI_COMMAND_SERR;
423	r = child->resource[0];
424	if(r && r->start) {
425		command |= PCI_COMMAND_IO;
426	}
427	r = child->resource[1];
428	if(r && r->start) {
429		command |= PCI_COMMAND_MEMORY;
430	}
431	r = child->resource[2];
432	if(r && r->start) {
433		command |= PCI_COMMAND_MEMORY;
434	}
435	rc = pci_write_config_word(dev, PCI_COMMAND, command);
436	if(rc) {
437		err("Error setting command register");
438		return rc;
439	}
440
441	/* Set bridge control register */
442	command = PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR | PCI_BRIDGE_CTL_NO_ISA;
443	rc = pci_write_config_word(dev, PCI_BRIDGE_CONTROL, command);
444	if(rc) {
445		err("Error setting bridge control register");
446		return rc;
447	}
448	dbg("%s - exit", __FUNCTION__);
449	return 0;
450}
451
452static int configure_visit_pci_dev(struct pci_dev_wrapped *wrapped_dev,
453				   struct pci_bus_wrapped *wrapped_bus)
454{
455	int rc;
456	struct pci_dev *dev = wrapped_dev->dev;
457	struct pci_bus *bus = wrapped_bus->bus;
458	struct slot* slot;
459
460	dbg("%s - enter", __FUNCTION__);
461
462	/*
463	 * We need to fix up the hotplug representation with the Linux
464	 * representation.
465	 */
466	if(wrapped_dev->data) {
467		slot = (struct slot*) wrapped_dev->data;
468		slot->dev = dev;
469	}
470
471	/* If it's a bridge, scan behind it for devices */
472	if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
473		rc = cpci_configure_bridge(bus, dev);
474		if(rc)
475			return rc;
476	}
477
478	/* Actually configure device */
479	if(dev) {
480		rc = cpci_configure_dev(bus, dev);
481		if(rc)
482			return rc;
483	}
484	dbg("%s - exit", __FUNCTION__);
485	return 0;
486}
487
488static int unconfigure_visit_pci_dev_phase2(struct pci_dev_wrapped *wrapped_dev,
489					    struct pci_bus_wrapped *wrapped_bus)
490{
491	struct pci_dev *dev = wrapped_dev->dev;
492	struct slot* slot;
493
494	dbg("%s - enter", __FUNCTION__);
495	if(!dev)
496		return -ENODEV;
497
498	/* Remove the Linux representation */
499	if(pci_remove_device_safe(dev)) {
500		err("Could not remove device\n");
501		return -1;
502	}
503
504	/*
505	 * Now remove the hotplug representation.
506	 */
507	if(wrapped_dev->data) {
508		slot = (struct slot*) wrapped_dev->data;
509		slot->dev = NULL;
510	} else {
511		dbg("No hotplug representation for %02x:%02x.%x",
512		    dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
513	}
514	dbg("%s - exit", __FUNCTION__);
515	return 0;
516}
517
518static int unconfigure_visit_pci_bus_phase2(struct pci_bus_wrapped *wrapped_bus,
519					    struct pci_dev_wrapped *wrapped_dev)
520{
521	struct pci_bus *bus = wrapped_bus->bus;
522	struct pci_bus *parent = bus->self->bus;
523
524	dbg("%s - enter", __FUNCTION__);
525
526	/* The cleanup code for proc entries regarding buses should be in the kernel... */
527	if(bus->procdir)
528		dbg("detach_pci_bus %s", bus->procdir->name);
529	pci_proc_detach_bus(bus);
530
531	/* The cleanup code should live in the kernel... */
532	bus->self->subordinate = NULL;
533
534	/* unlink from parent bus */
535	list_del(&bus->node);
536
537	/* Now, remove */
538	if(bus)
539		kfree(bus);
540
541	/* Update parent's subordinate field */
542	if(parent) {
543		u8 n = pci_bus_max_busnr(parent);
544		if(n < parent->subordinate) {
545			parent->subordinate = n;
546			pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, n);
547		}
548	}
549	dbg("%s - exit", __FUNCTION__);
550	return 0;
551}
552
553static struct pci_visit configure_functions = {
554	.visit_pci_dev = configure_visit_pci_dev,
555};
556
557static struct pci_visit unconfigure_functions_phase2 = {
558	.post_visit_pci_bus = unconfigure_visit_pci_bus_phase2,
559	.post_visit_pci_dev = unconfigure_visit_pci_dev_phase2
560};
561
562
563int cpci_configure_slot(struct slot* slot)
564{
565	int rc = 0;
566
567	dbg("%s - enter", __FUNCTION__);
568
569	if(slot->dev == NULL) {
570		dbg("pci_dev null, finding %02x:%02x:%x",
571		    slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn));
572		slot->dev = pci_find_slot(slot->bus->number, slot->devfn);
573	}
574
575	/* Still NULL? Well then scan for it! */
576	if(slot->dev == NULL) {
577		int n;
578		dbg("pci_dev still null");
579
580		/*
581		 * This will generate pci_dev structures for all functions, but
582		 * we will only call this case when lookup fails.
583		 */
584		n = pci_scan_slot(slot->bus, slot->devfn);
585		dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n);
586		if(n > 0)
587			pci_bus_add_devices(slot->bus);
588		slot->dev = pci_find_slot(slot->bus->number, slot->devfn);
589		if(slot->dev == NULL) {
590			err("Could not find PCI device for slot %02x", slot->number);
591			return 0;
592		}
593	}
594	dbg("slot->dev = %p", slot->dev);
595	if(slot->dev) {
596		struct pci_dev *dev;
597		struct pci_dev_wrapped wrapped_dev;
598		struct pci_bus_wrapped wrapped_bus;
599		int i;
600
601		memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
602		memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
603
604		for (i = 0; i < 8; i++) {
605			dev = pci_find_slot(slot->bus->number,
606					    PCI_DEVFN(PCI_SLOT(slot->dev->devfn), i));
607			if(!dev)
608				continue;
609			wrapped_dev.dev = dev;
610			wrapped_bus.bus = slot->dev->bus;
611			if(i)
612				wrapped_dev.data = NULL;
613			else
614				wrapped_dev.data = (void*) slot;
615			rc = pci_visit_dev(&configure_functions, &wrapped_dev, &wrapped_bus);
616		}
617	}
618
619	dbg("%s - exit, rc = %d", __FUNCTION__, rc);
620	return rc;
621}
622
623int cpci_unconfigure_slot(struct slot* slot)
624{
625	int rc = 0;
626	int i;
627	struct pci_dev_wrapped wrapped_dev;
628	struct pci_bus_wrapped wrapped_bus;
629	struct pci_dev *dev;
630
631	dbg("%s - enter", __FUNCTION__);
632
633	if(!slot->dev) {
634		err("No device for slot %02x\n", slot->number);
635		return -ENODEV;
636	}
637
638	memset(&wrapped_dev, 0, sizeof (struct pci_dev_wrapped));
639	memset(&wrapped_bus, 0, sizeof (struct pci_bus_wrapped));
640
641	for (i = 0; i < 8; i++) {
642		dev = pci_find_slot(slot->bus->number,
643				    PCI_DEVFN(PCI_SLOT(slot->devfn), i));
644		if(dev) {
645			wrapped_dev.dev = dev;
646			wrapped_bus.bus = dev->bus;
647 			if(i)
648 				wrapped_dev.data = NULL;
649 			else
650 				wrapped_dev.data = (void*) slot;
651			dbg("%s - unconfigure phase 2", __FUNCTION__);
652			rc = pci_visit_dev(&unconfigure_functions_phase2,
653					   &wrapped_dev,
654					   &wrapped_bus);
655			if(rc)
656				break;
657		}
658	}
659	dbg("%s - exit, rc = %d", __FUNCTION__, rc);
660	return rc;
661}
662