xref: /netbsd-src/sys/dev/cardbus/rbus_ppb.c (revision 9ad90ada5a40281d2484b05cab5592e1b91ff587)
1*9ad90adaSthorpej /*	$NetBSD: rbus_ppb.c,v 1.50 2022/09/25 17:33:19 thorpej Exp $	*/
2c34df0c3Smcr 
3c34df0c3Smcr /*
4c34df0c3Smcr  * Copyright (c) 1999 The NetBSD Foundation, Inc.
5c34df0c3Smcr  * All rights reserved.
6c34df0c3Smcr  *
7c34df0c3Smcr  * This code is derived from software contributed to The NetBSD Foundation
8c34df0c3Smcr  * by Michael Richardson <mcr@sandelman.ottawa.on.ca>
9c34df0c3Smcr  *
10c34df0c3Smcr  * Redistribution and use in source and binary forms, with or without
11c34df0c3Smcr  * modification, are permitted provided that the following conditions
12c34df0c3Smcr  * are met:
13c34df0c3Smcr  * 1. Redistributions of source code must retain the above copyright
14c34df0c3Smcr  *    notice, this list of conditions and the following disclaimer.
15c34df0c3Smcr  * 2. Redistributions in binary form must reproduce the above copyright
16c34df0c3Smcr  *    notice, this list of conditions and the following disclaimer in the
17c34df0c3Smcr  *    documentation and/or other materials provided with the distribution.
18c34df0c3Smcr  *
19c34df0c3Smcr  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20c34df0c3Smcr  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21c34df0c3Smcr  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22c34df0c3Smcr  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23c34df0c3Smcr  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24c34df0c3Smcr  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25c34df0c3Smcr  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26c34df0c3Smcr  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27c34df0c3Smcr  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28c34df0c3Smcr  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29c34df0c3Smcr  * POSSIBILITY OF SUCH DAMAGE.
30c34df0c3Smcr  */
31c34df0c3Smcr 
32c34df0c3Smcr /*
33c34df0c3Smcr  * CardBus front-end for the Intel/Digital DECchip 21152 PCI-PCI bridge
34c34df0c3Smcr  */
35c34df0c3Smcr 
36f61cbe74Slukem #include <sys/cdefs.h>
37*9ad90adaSthorpej __KERNEL_RCSID(0, "$NetBSD: rbus_ppb.c,v 1.50 2022/09/25 17:33:19 thorpej Exp $");
38f61cbe74Slukem 
39c34df0c3Smcr #include <sys/param.h>
40c34df0c3Smcr #include <sys/systm.h>
41c34df0c3Smcr #include <sys/mbuf.h>
42c34df0c3Smcr #include <sys/kernel.h>
43c34df0c3Smcr #include <sys/socket.h>
44c34df0c3Smcr #include <sys/ioctl.h>
45c34df0c3Smcr #include <sys/errno.h>
46c34df0c3Smcr #include <sys/device.h>
4755ce6763Sdyoung #include <sys/kmem.h>
48c34df0c3Smcr 
49c34df0c3Smcr #include <machine/endian.h>
50c34df0c3Smcr 
51a2a38285Sad #include <sys/bus.h>
52a2a38285Sad #include <sys/intr.h>
53c34df0c3Smcr 
54c34df0c3Smcr #include <dev/pci/pcivar.h>
55c34df0c3Smcr #include <dev/pci/pcireg.h>
56c34df0c3Smcr #include <dev/pci/pcidevs.h>
57c34df0c3Smcr #include <dev/pci/ppbreg.h>
58c34df0c3Smcr 
59c34df0c3Smcr #include <dev/ic/i82365reg.h>
60c34df0c3Smcr 
611ca3ef38Sdrochner #include <dev/cardbus/rbus.h>
62c34df0c3Smcr #include <dev/pci/pccbbreg.h>
63c34df0c3Smcr #include <dev/pci/pccbbvar.h>
64c34df0c3Smcr 
65c34df0c3Smcr #include <dev/cardbus/cardbusvar.h>
66eed3298aSmycroft #include <dev/pci/pcidevs.h>
67c34df0c3Smcr 
689709f2afSjmcneill #include <x86/pci/pci_addr_fixup.h>
699709f2afSjmcneill #include <x86/pci/pci_bus_fixup.h>
70c34df0c3Smcr #include <i386/pci/pci_intr_fixup.h>
71c34df0c3Smcr #include <i386/pci/pcibios.h>
72c34df0c3Smcr 
73c34df0c3Smcr struct ppb_softc;
74c34df0c3Smcr 
75529e91fcScegger static int  ppb_cardbus_match(device_t, cfdata_t, void *);
76529e91fcScegger static void ppb_cardbus_attach(device_t, device_t, void *);
77529e91fcScegger static int  ppb_activate(device_t, enum devact);
781fbab2d8Sdrochner int rppbprint(void *, const char *);
791fbab2d8Sdrochner int rbus_intr_fixup(pci_chipset_tag_t, int, int, int);
801fbab2d8Sdrochner void rbus_do_header_fixup(pci_chipset_tag_t, pcitag_t, void *);
81c34df0c3Smcr 
821fbab2d8Sdrochner static void rbus_pci_phys_allocate(pci_chipset_tag_t, pcitag_t, void *);
83c34df0c3Smcr 
841fbab2d8Sdrochner static int rbus_do_phys_allocate(pci_chipset_tag_t, pcitag_t, int,
851fbab2d8Sdrochner 				 void *, int, bus_addr_t *, bus_size_t);
86c34df0c3Smcr 
871fbab2d8Sdrochner static void rbus_pci_phys_countspace(pci_chipset_tag_t, pcitag_t, void *);
88c34df0c3Smcr 
891fbab2d8Sdrochner static int rbus_do_phys_countspace(pci_chipset_tag_t, pcitag_t, int,
901fbab2d8Sdrochner 				   void *, int, bus_addr_t *, bus_size_t);
91c34df0c3Smcr 
921fbab2d8Sdrochner unsigned int rbus_round_up(unsigned int, unsigned int);
93c34df0c3Smcr 
94c34df0c3Smcr 
95c34df0c3Smcr struct ppb_cardbus_softc {
960d1213e5Sjoerg   device_t sc_dev;
97204183c0Sthorpej   pcitag_t sc_tag;
98c34df0c3Smcr   int foo;
99c34df0c3Smcr };
100c34df0c3Smcr 
1010d1213e5Sjoerg CFATTACH_DECL_NEW(rbus_ppb, sizeof(struct ppb_cardbus_softc),
1026d8bb433Sdyoung     ppb_cardbus_match, ppb_cardbus_attach, NULL, ppb_activate);
103c34df0c3Smcr 
104c34df0c3Smcr #ifdef  CBB_DEBUG
105c34df0c3Smcr int rbus_ppb_debug = 0;   /* hack with kdb */
106c34df0c3Smcr #define DPRINTF(X) if(rbus_ppb_debug) printf X
107c34df0c3Smcr #else
108c34df0c3Smcr #define DPRINTF(X)
109c34df0c3Smcr #endif
110c34df0c3Smcr 
111c34df0c3Smcr static int
ppb_cardbus_match(device_t parent,cfdata_t match,void * aux)112529e91fcScegger ppb_cardbus_match(device_t parent, cfdata_t match, void *aux)
113c34df0c3Smcr {
114c34df0c3Smcr 	struct cardbus_attach_args *ca = aux;
115c34df0c3Smcr 
116508883c1Sdyoung 	if (PCI_VENDOR(ca->ca_id) ==  PCI_VENDOR_DEC &&
117508883c1Sdyoung 	    PCI_PRODUCT(ca->ca_id) == PCI_PRODUCT_DEC_21152)
118c34df0c3Smcr 		return (1);
119c34df0c3Smcr 
120c34df0c3Smcr 	if(PCI_CLASS(ca->ca_class) == PCI_CLASS_BRIDGE &&
121c34df0c3Smcr 	   PCI_SUBCLASS(ca->ca_class) == PCI_SUBCLASS_BRIDGE_PCI) {
122c34df0c3Smcr 	  /* XXX */
123c34df0c3Smcr 	  printf("recognizing generic bridge chip\n");
124c34df0c3Smcr 	}
125c34df0c3Smcr 
126c34df0c3Smcr 	return (0);
127c34df0c3Smcr }
128c34df0c3Smcr 
129c34df0c3Smcr 
130c34df0c3Smcr int
rppbprint(void * aux,const char * pnp)131454af1c0Sdsl rppbprint(void *aux, const char *pnp)
132c34df0c3Smcr {
133c34df0c3Smcr 	struct pcibus_attach_args *pba = aux;
134c34df0c3Smcr 
135c34df0c3Smcr 	/* only PCIs can attach to PPBs; easy. */
136c34df0c3Smcr 	if (pnp)
13772a7af27Sthorpej 		aprint_normal("pci at %s", pnp);
13872a7af27Sthorpej 	aprint_normal(" bus %d (rbus)", pba->pba_bus);
139c34df0c3Smcr 	return (UNCONF);
140c34df0c3Smcr }
141c34df0c3Smcr 
142c34df0c3Smcr int
rbus_intr_fixup(pci_chipset_tag_t pc,int minbus,int maxbus,int line)143c34df0c3Smcr rbus_intr_fixup(pci_chipset_tag_t pc,
144c34df0c3Smcr 		int minbus,
145c34df0c3Smcr 		int maxbus,
146c34df0c3Smcr 		int line)
147c34df0c3Smcr {
148c34df0c3Smcr   pci_device_foreach_min(pc, minbus,
149c34df0c3Smcr 			 maxbus, rbus_do_header_fixup, (void *)&line);
150c34df0c3Smcr   return 0;
151c34df0c3Smcr }
152c34df0c3Smcr 
153c34df0c3Smcr void
rbus_do_header_fixup(pci_chipset_tag_t pc,pcitag_t tag,void * context)154454af1c0Sdsl rbus_do_header_fixup(pci_chipset_tag_t pc, pcitag_t tag, void *context)
155c34df0c3Smcr {
156c34df0c3Smcr   int bus, device, function;
157aa71c16aSuebayasi   pcireg_t intr;
158c34df0c3Smcr   int *pline = (int *)context;
159c34df0c3Smcr   int line = *pline;
160c34df0c3Smcr 
161c34df0c3Smcr   pci_decompose_tag(pc, tag, &bus, &device, &function);
162c34df0c3Smcr 
163c34df0c3Smcr   intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
164c34df0c3Smcr 
165c34df0c3Smcr   intr &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
166c34df0c3Smcr   intr |= (line << PCI_INTERRUPT_LINE_SHIFT);
167c34df0c3Smcr   pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
168c34df0c3Smcr 
169c34df0c3Smcr }
170c34df0c3Smcr 
171c34df0c3Smcr /*
172c34df0c3Smcr  * This function takes a range of PCI bus numbers and
173c34df0c3Smcr  * allocates space for all devices found in this space (the BARs) from
174c34df0c3Smcr  * the rbus space maps (I/O and memory).
175c34df0c3Smcr  *
176c34df0c3Smcr  * It assumes that "rbus" is defined. The whole concept does.
177c34df0c3Smcr  *
178c34df0c3Smcr  * It uses pci_device_foreach_min() to call rbus_pci_phys_allocate.
179c34df0c3Smcr  * This function is mostly stolen from
180c34df0c3Smcr  *     pci_addr_fixup.c:pciaddr_resource_reserve.
181c34df0c3Smcr  *
182c34df0c3Smcr  */
183c34df0c3Smcr struct rbus_pci_addr_fixup_context {
184c34df0c3Smcr   struct ppb_cardbus_softc *csc;
185c34df0c3Smcr   cardbus_chipset_tag_t ct;
186c34df0c3Smcr   struct cardbus_softc *sc;
187c34df0c3Smcr   struct cardbus_attach_args *caa;
188c34df0c3Smcr   int    minbus;
189c34df0c3Smcr   int    maxbus;
190c34df0c3Smcr   bus_size_t  *bussize_ioreqs;
191c34df0c3Smcr   bus_size_t  *bussize_memreqs;
192c34df0c3Smcr   rbus_tag_t   *iobustags;
193c34df0c3Smcr   rbus_tag_t   *membustags;
194c34df0c3Smcr };
195c34df0c3Smcr 
196c34df0c3Smcr unsigned int
rbus_round_up(unsigned int size,unsigned int minval)1971fbab2d8Sdrochner rbus_round_up(unsigned int size, unsigned int minval)
198c34df0c3Smcr {
199c34df0c3Smcr   unsigned int power2;
200c34df0c3Smcr 
201c34df0c3Smcr   if(size == 0) {
202c34df0c3Smcr     return 0;
203c34df0c3Smcr   }
204c34df0c3Smcr 
2051fbab2d8Sdrochner   power2=minval;
206c34df0c3Smcr 
207c34df0c3Smcr   while(power2 < (1 << 31) &&
208c34df0c3Smcr 	power2 < size) {
209c34df0c3Smcr     power2 = power2 << 1;
210c34df0c3Smcr   }
211c34df0c3Smcr 
212c34df0c3Smcr   return power2;
213c34df0c3Smcr }
214c34df0c3Smcr 
215c34df0c3Smcr static void
rbus_pci_addr_fixup(struct ppb_cardbus_softc * csc,cardbus_chipset_tag_t ct,struct cardbus_softc * sc,pci_chipset_tag_t pc,struct cardbus_attach_args * caa,int minbus,const int maxbus)216c34df0c3Smcr rbus_pci_addr_fixup(struct ppb_cardbus_softc *csc,
217c34df0c3Smcr 		    cardbus_chipset_tag_t ct,
218c34df0c3Smcr 		    struct cardbus_softc *sc,
219c34df0c3Smcr 		    pci_chipset_tag_t     pc,
220c34df0c3Smcr 		    struct cardbus_attach_args *caa,
22155ce6763Sdyoung 		    int minbus, const int maxbus)
222c34df0c3Smcr {
223c34df0c3Smcr 	struct rbus_pci_addr_fixup_context rct;
22455ce6763Sdyoung 	const size_t size = sizeof(bus_size_t[maxbus+1]);
22555ce6763Sdyoung 	int busnum;
226c34df0c3Smcr 	bus_addr_t start;
227c34df0c3Smcr 	bus_space_handle_t handle;
228c34df0c3Smcr 	u_int32_t reg;
229c34df0c3Smcr 
230c34df0c3Smcr 	rct.csc=csc;
231c34df0c3Smcr 	rct.ct=ct;
232c34df0c3Smcr 	rct.sc=sc;
233c34df0c3Smcr 	rct.caa=caa;
234c34df0c3Smcr 	rct.minbus = minbus;
235c34df0c3Smcr 	rct.maxbus = maxbus;
236fd34ea77Schs 	rct.bussize_ioreqs = kmem_zalloc(size, KM_SLEEP);
237fd34ea77Schs 	rct.bussize_memreqs = kmem_zalloc(size, KM_SLEEP);
238fd34ea77Schs 	rct.iobustags = kmem_zalloc(maxbus * sizeof(rbus_tag_t), KM_SLEEP);
239fd34ea77Schs 	rct.membustags = kmem_zalloc(maxbus * sizeof(rbus_tag_t), KM_SLEEP);
240c34df0c3Smcr 
241c34df0c3Smcr 	printf("%s: sizing buses %d-%d\n",
2420d1213e5Sjoerg 	       device_xname(rct.csc->sc_dev),
243c34df0c3Smcr 	       minbus, maxbus);
244c34df0c3Smcr 
245c34df0c3Smcr 	pci_device_foreach_min(pc, minbus, maxbus,
246c34df0c3Smcr 			       rbus_pci_phys_countspace, &rct);
247c34df0c3Smcr 
248c34df0c3Smcr 	/*
249c34df0c3Smcr 	 * we need to determine amount of address space for each
250c34df0c3Smcr 	 * bus. To do this, we have to roll up amounts and then
251c34df0c3Smcr 	 * we need to divide up the cardbus's extent to allocate
252c34df0c3Smcr 	 * some space to each bus.
253c34df0c3Smcr 	 */
254c34df0c3Smcr 
255c34df0c3Smcr 	for(busnum=maxbus; busnum > minbus; busnum--) {
256c34df0c3Smcr 	  if(pci_bus_parent[busnum] != 0) {
257c34df0c3Smcr 	    if(pci_bus_parent[busnum] < minbus ||
258c34df0c3Smcr 	       pci_bus_parent[busnum] >= maxbus) {
259c34df0c3Smcr 	      printf("%s: bus %d has illegal parent %d\n",
2600d1213e5Sjoerg 		     device_xname(rct.csc->sc_dev),
261c34df0c3Smcr 		     busnum, pci_bus_parent[busnum]);
262c34df0c3Smcr 	      continue;
263c34df0c3Smcr 	    }
264c34df0c3Smcr 
265c34df0c3Smcr 	    /* first round amount of space up */
266c34df0c3Smcr 	    rct.bussize_ioreqs[busnum] =
26779770474Smsaitoh 	      rbus_round_up(rct.bussize_ioreqs[busnum],  PCI_BRIDGE_IO_MIN);
268c34df0c3Smcr 	    rct.bussize_ioreqs[pci_bus_parent[busnum]] +=
269c34df0c3Smcr 	      rct.bussize_ioreqs[busnum];
270c34df0c3Smcr 
271c34df0c3Smcr 	    rct.bussize_memreqs[busnum] =
27279770474Smsaitoh 	      rbus_round_up(rct.bussize_memreqs[busnum], PCI_BRIDGE_MEM_MIN);
273c34df0c3Smcr 	    rct.bussize_memreqs[pci_bus_parent[busnum]] +=
274c34df0c3Smcr 	      rct.bussize_memreqs[busnum];
275c34df0c3Smcr 
276c34df0c3Smcr 	  }
277c34df0c3Smcr 	}
278c34df0c3Smcr 
279c34df0c3Smcr 	rct.bussize_ioreqs[minbus] =
28079770474Smsaitoh 	  rbus_round_up(rct.bussize_ioreqs[minbus], PCI_BRIDGE_IO_MIN);
28179770474Smsaitoh 	rct.bussize_memreqs[minbus] =  /* XXX Not 8 but PCI_BRIDGE_MEM_MIN ? */
282c34df0c3Smcr 	  rbus_round_up(rct.bussize_memreqs[minbus], 8);
283c34df0c3Smcr 
28455ce6763Sdyoung 	printf("%s: total needs IO %08zx and MEM %08zx\n",
2850d1213e5Sjoerg 	       device_xname(rct.csc->sc_dev),
286c34df0c3Smcr 	       rct.bussize_ioreqs[minbus], rct.bussize_memreqs[minbus]);
287c34df0c3Smcr 
288c34df0c3Smcr 	if(!caa->ca_rbus_iot) {
289c34df0c3Smcr 	  panic("no iot bus");
290c34df0c3Smcr 	}
291c34df0c3Smcr 
292c34df0c3Smcr 	if(rct.bussize_ioreqs[minbus]) {
293c34df0c3Smcr 	  if(rbus_space_alloc(caa->ca_rbus_iot, 0,
294c34df0c3Smcr 			      rct.bussize_ioreqs[minbus],
295c34df0c3Smcr 			      rct.bussize_ioreqs[minbus]-1 /* mask  */,
296c34df0c3Smcr 			      rct.bussize_ioreqs[minbus] /* align */,
297c34df0c3Smcr 			      /* flags */ 0,
298c34df0c3Smcr 			      &start,
299c34df0c3Smcr 			      &handle) != 0) {
30055ce6763Sdyoung 	    panic("rbus_ppb: can not allocate %zu bytes in IO bus %d",
301c34df0c3Smcr 		  rct.bussize_ioreqs[minbus], minbus);
302c34df0c3Smcr 	  }
303c34df0c3Smcr 	  rct.iobustags[minbus]=rbus_new(caa->ca_rbus_iot,
304c34df0c3Smcr 					 start,
305c34df0c3Smcr 					 rct.bussize_ioreqs[minbus],
306c34df0c3Smcr 					 0 /* offset to add to physical address
307c34df0c3Smcr 					      to make processor address */,
308c34df0c3Smcr 					 RBUS_SPACE_DEDICATE);
309c34df0c3Smcr 	}
310c34df0c3Smcr 
311c34df0c3Smcr 	if(rct.bussize_memreqs[minbus]) {
312c34df0c3Smcr 	  if(rbus_space_alloc(caa->ca_rbus_memt, 0,
313c34df0c3Smcr 			      rct.bussize_memreqs[minbus],
314c34df0c3Smcr 			      rct.bussize_memreqs[minbus]-1 /* mask */,
315c34df0c3Smcr 			      rct.bussize_memreqs[minbus] /* align */,
316c34df0c3Smcr 			      /* flags */ 0,
317c34df0c3Smcr 			      &start,
318c34df0c3Smcr 			      &handle) != 0) {
31955ce6763Sdyoung 	    panic("%s: can not allocate %zu bytes in MEM bus %d",
3200d1213e5Sjoerg 		  device_xname(rct.csc->sc_dev),
321c34df0c3Smcr 		  rct.bussize_memreqs[minbus], minbus);
322c34df0c3Smcr 	  }
323c34df0c3Smcr 	  rct.membustags[minbus]=rbus_new(caa->ca_rbus_memt,
324c34df0c3Smcr 					  start,
325c34df0c3Smcr 					  rct.bussize_memreqs[minbus],
326c34df0c3Smcr 					  0 /* offset to add to physical
327c34df0c3Smcr 					       address to make processor
328c34df0c3Smcr 					       address */,
329c34df0c3Smcr 					  RBUS_SPACE_DEDICATE);
330c34df0c3Smcr 	}
331c34df0c3Smcr 
332c34df0c3Smcr 	for(busnum=minbus+1; busnum <= maxbus; busnum++) {
333c34df0c3Smcr 	  int busparent;
334c34df0c3Smcr 
335c34df0c3Smcr 	  busparent = pci_bus_parent[busnum];
336c34df0c3Smcr 
33755ce6763Sdyoung 	  printf("%s: bus %d (parent=%d) needs IO %08zx and MEM %08zx\n",
3380d1213e5Sjoerg 		 device_xname(rct.csc->sc_dev),
339c34df0c3Smcr 		 busnum,
340c34df0c3Smcr 		 busparent,
341c34df0c3Smcr 		 rct.bussize_ioreqs[busnum],
342c34df0c3Smcr 		 rct.bussize_memreqs[busnum]);
343c34df0c3Smcr 
344c34df0c3Smcr 	  if(busparent > maxbus) {
345c34df0c3Smcr 	    panic("rbus_ppb: illegal parent");
346c34df0c3Smcr 	  }
347c34df0c3Smcr 
348c34df0c3Smcr 	  if(rct.bussize_ioreqs[busnum]) {
349c34df0c3Smcr 	    if(rbus_space_alloc(rct.iobustags[busparent],
350c34df0c3Smcr 				0,
351c34df0c3Smcr 				rct.bussize_ioreqs[busnum],
352c34df0c3Smcr 				rct.bussize_ioreqs[busnum]-1 /*mask */,
353c34df0c3Smcr 				rct.bussize_ioreqs[busnum] /* align */,
354c34df0c3Smcr 				/* flags */ 0,
355c34df0c3Smcr 				&start,
356c34df0c3Smcr 				&handle) != 0) {
35755ce6763Sdyoung 	      panic("rbus_ppb: can not allocate %zu bytes in IO bus %d",
358c34df0c3Smcr 		    rct.bussize_ioreqs[busnum], busnum);
359c34df0c3Smcr 	    }
360c34df0c3Smcr 	    rct.iobustags[busnum]=rbus_new(rct.iobustags[busparent],
361c34df0c3Smcr 					   start,
362c34df0c3Smcr 					   rct.bussize_ioreqs[busnum],
363c34df0c3Smcr 					   0 /* offset to add to physical
364c34df0c3Smcr 						address
365c34df0c3Smcr 						to make processor address */,
366c34df0c3Smcr 					   RBUS_SPACE_DEDICATE);
367c34df0c3Smcr 
368c34df0c3Smcr 	    /* program the bridge */
369c34df0c3Smcr 
370c34df0c3Smcr 	    /* enable I/O space */
371c34df0c3Smcr 	    reg = pci_conf_read(pc, pci_bus_tag[busnum],
372c34df0c3Smcr 				PCI_COMMAND_STATUS_REG);
373c34df0c3Smcr 	    reg |= PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE;
374c34df0c3Smcr 	    pci_conf_write(pc, pci_bus_tag[busnum],
375c34df0c3Smcr 			   PCI_COMMAND_STATUS_REG, reg);
376c34df0c3Smcr 
377c34df0c3Smcr 	    /* now init the limit register for I/O */
37879770474Smsaitoh 	    pci_conf_write(pc, pci_bus_tag[busnum], PCI_BRIDGE_STATIO_REG,
37979770474Smsaitoh 		__SHIFTIN((start >> 8)
38079770474Smsaitoh 		    & PCI_BRIDGE_STATIO_IOADDR, PCI_BRIDGE_STATIO_IOBASE) |
38179770474Smsaitoh 		__SHIFTIN(((start + rct.bussize_ioreqs[busnum] + 4095) >> 8)
38279770474Smsaitoh 		    & PCI_BRIDGE_STATIO_IOADDR, PCI_BRIDGE_STATIO_IOLIMIT));
383c34df0c3Smcr 	  }
384c34df0c3Smcr 
385c34df0c3Smcr 	  if(rct.bussize_memreqs[busnum]) {
386c34df0c3Smcr 	    if(rbus_space_alloc(rct.membustags[busparent],
387c34df0c3Smcr 				0,
388c34df0c3Smcr 				rct.bussize_memreqs[busnum] /* size  */,
389c34df0c3Smcr 				rct.bussize_memreqs[busnum]-1 /*mask */,
390c34df0c3Smcr 				rct.bussize_memreqs[busnum] /* align */,
391c34df0c3Smcr 				/* flags */ 0,
392c34df0c3Smcr 				&start,
393c34df0c3Smcr 				&handle) != 0) {
39455ce6763Sdyoung 	      panic("rbus_ppb: can not allocate %zu bytes in MEM bus %d",
395c34df0c3Smcr 		    rct.bussize_memreqs[busnum], busnum);
396c34df0c3Smcr 	    }
397c34df0c3Smcr 	    rct.membustags[busnum]=rbus_new(rct.membustags[busparent],
398c34df0c3Smcr 					    start,
399c34df0c3Smcr 					    rct.bussize_memreqs[busnum],
400c34df0c3Smcr 					    0 /* offset to add to physical
401c34df0c3Smcr 						 address to make processor
402c34df0c3Smcr 						 address */,
403c34df0c3Smcr 					    RBUS_SPACE_DEDICATE);
404c34df0c3Smcr 
405c34df0c3Smcr 	    /* program the bridge */
406c34df0c3Smcr 	    /* enable memory space */
407c34df0c3Smcr 	    reg = pci_conf_read(pc, pci_bus_tag[busnum],
408c34df0c3Smcr 				PCI_COMMAND_STATUS_REG);
409c34df0c3Smcr 	    reg |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
410c34df0c3Smcr 	    pci_conf_write(pc, pci_bus_tag[busnum],
411c34df0c3Smcr 			   PCI_COMMAND_STATUS_REG, reg);
412c34df0c3Smcr 
413c34df0c3Smcr 	    /* now init the limit register for memory */
41479770474Smsaitoh 	    pci_conf_write(pc, pci_bus_tag[busnum], PCI_BRIDGE_MEMORY_REG,
41579770474Smsaitoh 		__SHIFTIN((start >> 16) & PCI_BRIDGE_MEMORY_ADDR,
41679770474Smsaitoh 		    PCI_BRIDGE_MEMORY_BASE) |
417e370c0d5Smsaitoh 		__SHIFTIN(((start + rct.bussize_memreqs[busnum]
418e370c0d5Smsaitoh 			    + PCI_BRIDGE_MEM_MIN - 1) >> 16)
419e370c0d5Smsaitoh 		    & PCI_BRIDGE_MEMORY_ADDR, PCI_BRIDGE_MEMORY_LIMIT));
420c34df0c3Smcr 
421c34df0c3Smcr 	    /* and set the prefetchable limits as well */
42279770474Smsaitoh 	    pci_conf_write(pc, pci_bus_tag[busnum], PCI_BRIDGE_PREFETCHMEM_REG,
42379770474Smsaitoh 		__SHIFTIN((start >> 16) & PCI_BRIDGE_PREFETCHMEM_ADDR,
42479770474Smsaitoh 		    PCI_BRIDGE_PREFETCHMEM_BASE) |
425e370c0d5Smsaitoh 		__SHIFTIN(((start + rct.bussize_memreqs[busnum]
426e370c0d5Smsaitoh 			    + PCI_BRIDGE_MEM_MIN - 1) >> 16)
427e370c0d5Smsaitoh 		    & PCI_BRIDGE_PREFETCHMEM_ADDR,
42879770474Smsaitoh 		    PCI_BRIDGE_PREFETCHMEM_LIMIT));
429c34df0c3Smcr 
430c34df0c3Smcr 	    /* pci_conf_print(pc, pci_bus_tag[busnum], NULL); */
431c34df0c3Smcr 	  }
432c34df0c3Smcr 	}
433c34df0c3Smcr 
434c34df0c3Smcr 	printf("%s: configuring buses %d-%d\n",
4350d1213e5Sjoerg 		device_xname(rct.csc->sc_dev),
436c34df0c3Smcr 	       minbus, maxbus);
437c34df0c3Smcr 	pci_device_foreach_min(pc, minbus, maxbus,
438c34df0c3Smcr 			       rbus_pci_phys_allocate, &rct);
43955ce6763Sdyoung 
44055ce6763Sdyoung 	kmem_free(rct.bussize_ioreqs, size);
44155ce6763Sdyoung 	kmem_free(rct.bussize_memreqs, size);
44255ce6763Sdyoung 	kmem_free(rct.iobustags, maxbus * sizeof(rbus_tag_t));
44355ce6763Sdyoung 	kmem_free(rct.membustags, maxbus * sizeof(rbus_tag_t));
444c34df0c3Smcr }
445c34df0c3Smcr 
446c34df0c3Smcr static void
rbus_pci_phys_countspace(pci_chipset_tag_t pc,pcitag_t tag,void * context)447454af1c0Sdsl rbus_pci_phys_countspace(pci_chipset_tag_t pc, pcitag_t tag, void *context)
448c34df0c3Smcr {
449c34df0c3Smcr         int bus, device, function;
450c34df0c3Smcr 	struct  rbus_pci_addr_fixup_context *rct =
451c34df0c3Smcr 	  (struct  rbus_pci_addr_fixup_context *)context;
452c34df0c3Smcr 
453c34df0c3Smcr 	pci_decompose_tag(pc, tag, &bus, &device, &function);
454c34df0c3Smcr 
455c34df0c3Smcr 	printf("%s: configuring device %02x:%02x:%02x\n",
4560d1213e5Sjoerg 	       device_xname(rct->csc->sc_dev),
457c34df0c3Smcr 	       bus, device, function);
458c34df0c3Smcr 
459c34df0c3Smcr 	pciaddr_resource_manage(pc, tag,
460c34df0c3Smcr 				rbus_do_phys_countspace, context);
461c34df0c3Smcr }
462c34df0c3Smcr 
463c34df0c3Smcr 
464c34df0c3Smcr int
rbus_do_phys_countspace(pci_chipset_tag_t pc,pcitag_t tag,int mapreg,void * ctx,int type,bus_addr_t * addr,bus_size_t size)46582357f6dSdsl rbus_do_phys_countspace(pci_chipset_tag_t pc, pcitag_t tag, int mapreg, void *ctx, int type, bus_addr_t *addr, bus_size_t size)
466c34df0c3Smcr {
467c34df0c3Smcr 	struct  rbus_pci_addr_fixup_context *rct =
468c34df0c3Smcr 	  (struct  rbus_pci_addr_fixup_context *)ctx;
469c34df0c3Smcr 	int bus, device, function;
470c34df0c3Smcr 
471c34df0c3Smcr 	pci_decompose_tag(pc, tag, &bus, &device, &function);
472c34df0c3Smcr 
473c34df0c3Smcr 	if(size > (1<<24)) {
474c34df0c3Smcr 	  printf("%s: skipping huge space request of size=%08x\n",
4750d1213e5Sjoerg 		 device_xname(rct->csc->sc_dev), (unsigned int)size);
476c34df0c3Smcr 	  return 0;
477c34df0c3Smcr 	}
478c34df0c3Smcr 
479c34df0c3Smcr 	if(PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) {
480c34df0c3Smcr 	  rct->bussize_ioreqs[bus] += size;
481c34df0c3Smcr 	} else {
482c34df0c3Smcr 	  rct->bussize_memreqs[bus]+= size;
483c34df0c3Smcr 	}
484c34df0c3Smcr 
485c34df0c3Smcr 	return 0;
486c34df0c3Smcr }
487c34df0c3Smcr 
488c34df0c3Smcr static void
rbus_pci_phys_allocate(pci_chipset_tag_t pc,pcitag_t tag,void * context)489454af1c0Sdsl rbus_pci_phys_allocate(pci_chipset_tag_t pc, pcitag_t tag, void *context)
490c34df0c3Smcr {
491c34df0c3Smcr         int bus, device, function, command;
492c34df0c3Smcr 	struct rbus_pci_addr_fixup_context *rct =
493c34df0c3Smcr 	  (struct rbus_pci_addr_fixup_context *)context;
494c34df0c3Smcr 
495c34df0c3Smcr 	pci_decompose_tag(pc, tag, &bus, &device, &function);
496c34df0c3Smcr 
497c34df0c3Smcr 	printf("%s: configuring device %02x:%02x:%02x\n",
4980d1213e5Sjoerg 	       device_xname(rct->csc->sc_dev),
499c34df0c3Smcr 	       bus, device, function);
500c34df0c3Smcr 
501c34df0c3Smcr 	pciaddr_resource_manage(pc, tag,
502c34df0c3Smcr 				rbus_do_phys_allocate, context);
503c34df0c3Smcr 
504c34df0c3Smcr 	/* now turn the device's memory and I/O on */
505c34df0c3Smcr 	command = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
506c34df0c3Smcr 	command |= PCI_COMMAND_IO_ENABLE|PCI_COMMAND_MEM_ENABLE;
507c34df0c3Smcr 	pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, command);
508c34df0c3Smcr }
509c34df0c3Smcr 
510c34df0c3Smcr int
rbus_do_phys_allocate(pci_chipset_tag_t pc,pcitag_t tag,int mapreg,void * ctx,int type,bus_addr_t * addr,bus_size_t size)51182357f6dSdsl rbus_do_phys_allocate(pci_chipset_tag_t pc, pcitag_t tag, int mapreg, void *ctx, int type, bus_addr_t *addr, bus_size_t size)
512c34df0c3Smcr {
513c34df0c3Smcr 	struct  rbus_pci_addr_fixup_context *rct =
514c34df0c3Smcr 	  (struct  rbus_pci_addr_fixup_context *)ctx;
515c34df0c3Smcr 	cardbus_chipset_tag_t ct     = rct->ct;
516c34df0c3Smcr 	struct cardbus_softc *sc     = rct->sc;
517c34df0c3Smcr 	cardbus_function_t       *cf = sc->sc_cf;
518c34df0c3Smcr 	rbus_tag_t          rbustag;
519c34df0c3Smcr 	bus_addr_t mask = size -1;
520c34df0c3Smcr 	bus_addr_t base = 0;
521c34df0c3Smcr 	bus_space_handle_t handle;
522c34df0c3Smcr 	int busflags = 0;
523c34df0c3Smcr 	int flags    = 0;
5241fbab2d8Sdrochner 	const char *bustype;
525c34df0c3Smcr 	int bus, device, function;
526c34df0c3Smcr 
527c34df0c3Smcr 	pci_decompose_tag(pc, tag, &bus, &device, &function);
528c34df0c3Smcr 
529c34df0c3Smcr 	/*
530c34df0c3Smcr 	 * some devices come up with garbage in them (Tulip?)
531c34df0c3Smcr 	 * we are in charge here, so give them address
532c34df0c3Smcr 	 * space anyway.
533c34df0c3Smcr 	 *
534c34df0c3Smcr 	 * XXX this may be due to no secondary PCI reset!!!
535c34df0c3Smcr 	 */
536c34df0c3Smcr #if 0
537c34df0c3Smcr 	if (*addr) {
538c34df0c3Smcr 		printf("Already allocated space at %08x\n",
539c34df0c3Smcr 		       (unsigned int)*addr);
540c34df0c3Smcr 		return (0);
541c34df0c3Smcr 	}
542c34df0c3Smcr #endif
543c34df0c3Smcr 
544c34df0c3Smcr 	if(size > (1<<24)) {
545c34df0c3Smcr 	  printf("%s: skipping huge space request of size=%08x\n",
5460d1213e5Sjoerg 		 device_xname(rct->csc->sc_dev), (unsigned int)size);
547c34df0c3Smcr 	  return 0;
548c34df0c3Smcr 	}
549c34df0c3Smcr 
550c34df0c3Smcr 	if(PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) {
551c34df0c3Smcr 	  rbustag = rct->iobustags[bus];
552c34df0c3Smcr 	  bustype = "io";
553c34df0c3Smcr 	} else {
554c34df0c3Smcr 	  rbustag = rct->membustags[bus];
555c34df0c3Smcr 	  bustype = "mem";
556c34df0c3Smcr 	}
557c34df0c3Smcr 
558c34df0c3Smcr 	if((*cf->cardbus_space_alloc)(ct, rbustag, base, size,
559c34df0c3Smcr 				      mask, size, busflags|flags,
560c34df0c3Smcr 				      addr, &handle)) {
561c34df0c3Smcr 	  printf("%s: no available resources (size=%08x) for bar %2d. fixup failed\n",
5620d1213e5Sjoerg 		 device_xname(rct->csc->sc_dev), (unsigned int)size, mapreg);
563c34df0c3Smcr 
564c34df0c3Smcr 	  *addr = 0;
565c34df0c3Smcr 	  pci_conf_write(pc, tag, mapreg, *addr);
566c34df0c3Smcr 	  return (1);
567c34df0c3Smcr 	}
568c34df0c3Smcr 
569c34df0c3Smcr 	printf("%s: alloc %s space of size %08x for %02d:%02d:%02d -> %08x\n",
5700d1213e5Sjoerg 	       device_xname(rct->csc->sc_dev),
571c34df0c3Smcr 	       bustype,
572c34df0c3Smcr 	       (unsigned int)size,
573c34df0c3Smcr 	       bus, device, function, (unsigned int)*addr);
574c34df0c3Smcr 
575c34df0c3Smcr 	/* write new address to PCI device configuration header */
576c34df0c3Smcr 	pci_conf_write(pc, tag, mapreg, *addr);
577c34df0c3Smcr 
578c34df0c3Smcr 	/* check */
579c34df0c3Smcr 	{
580c34df0c3Smcr 		DPRINTF(("%s: pci_addr_fixup: ",
5810d1213e5Sjoerg 			 device_xname(rct->csc->sc_dev)));
582c34df0c3Smcr #ifdef  CBB_DEBUG
583c34df0c3Smcr 		if(rbus_ppb_debug) { pciaddr_print_devid(pc, tag); }
584c34df0c3Smcr #endif
585c34df0c3Smcr 	}
586c34df0c3Smcr 
587c34df0c3Smcr 	/* double check that the value got inserted correctly */
588c34df0c3Smcr 	if (pciaddr_ioaddr(pci_conf_read(pc, tag, mapreg)) != *addr) {
589c34df0c3Smcr 		pci_conf_write(pc, tag, mapreg, 0); /* clear */
590c34df0c3Smcr 		printf("%s: fixup failed. (new address=%#x)\n",
5910d1213e5Sjoerg 		       device_xname(rct->csc->sc_dev),
592c34df0c3Smcr 		       (unsigned)*addr);
593c34df0c3Smcr 		return (1);
594c34df0c3Smcr 	}
595c34df0c3Smcr 
596c34df0c3Smcr 	DPRINTF(("new address 0x%08x\n",
597c34df0c3Smcr 		 (unsigned)*addr));
598c34df0c3Smcr 
599c34df0c3Smcr 	return (0);
600c34df0c3Smcr }
601c34df0c3Smcr 
602c34df0c3Smcr static void
ppb_cardbus_attach(device_t parent,device_t self,void * aux)6030d1213e5Sjoerg ppb_cardbus_attach(device_t parent, device_t self, void *aux)
604c34df0c3Smcr {
6050bb04182Sthorpej 	struct ppb_cardbus_softc *csc = device_private(self);
6063d7462a9Sjoerg 	struct cardbus_softc *parent_sc = device_private(parent);
607c34df0c3Smcr 	struct cardbus_attach_args *ca = aux;
608c34df0c3Smcr 	cardbus_devfunc_t ct = ca->ca_ct;
609c34df0c3Smcr 	cardbus_chipset_tag_t cc = ct->ct_cc;
610c34df0c3Smcr 	struct pccbb_softc *psc = (struct pccbb_softc *)cc;
611c34df0c3Smcr 	struct pcibus_attach_args pba;
612c34df0c3Smcr 	char devinfo[256];
613c34df0c3Smcr 	pcireg_t busdata;
614c34df0c3Smcr 	int minbus, maxbus;
615c34df0c3Smcr 
6160d1213e5Sjoerg 	csc->sc_dev = self;
6170d1213e5Sjoerg 
61861230437Sitojun 	pci_devinfo(ca->ca_id, ca->ca_class, 0, devinfo, sizeof(devinfo));
619c34df0c3Smcr 	printf(": %s (rev. 0x%02x)\n", devinfo, PCI_REVISION(ca->ca_class));
620c34df0c3Smcr 
6218089c2dcSdyoung 	csc->sc_tag = ca->ca_tag;
622204183c0Sthorpej 
62379770474Smsaitoh 	busdata = Cardbus_conf_read(ct, ca->ca_tag, PCI_BRIDGE_BUS_REG);
624c34df0c3Smcr 	minbus = pcibios_max_bus;
625130aed8eSlukem 	maxbus = minbus;		/* XXX; gcc */
626c34df0c3Smcr 
62779770474Smsaitoh 	if (PCI_BRIDGE_BUS_NUM_SECONDARY(busdata) == 0) {
628c0d1e7cbScegger 		aprint_error_dev(self, "not configured by system firmware calling pci_bus_fixup(%d)\n", 0);
629c34df0c3Smcr 
630c34df0c3Smcr 	  /*
631c34df0c3Smcr 	   * first, pull the reset wire on the secondary bridge
632c34df0c3Smcr 	   * to clear all devices
633c34df0c3Smcr 	   */
63479770474Smsaitoh 	  busdata = Cardbus_conf_read(ct, ca->ca_tag, PCI_BRIDGE_CONTROL_REG);
63579770474Smsaitoh 	  Cardbus_conf_write(ct, ca->ca_tag, PCI_BRIDGE_CONTROL_REG,
63679770474Smsaitoh 	      busdata | PCI_BRIDGE_CONTROL_SECBR);
637c34df0c3Smcr 	  delay(1);
63879770474Smsaitoh 	  Cardbus_conf_write(ct, ca->ca_tag, PCI_BRIDGE_CONTROL_REG,
639c34df0c3Smcr 			     busdata);
640c34df0c3Smcr 
641c34df0c3Smcr 	  /* then go initialize the bridge control registers */
642c34df0c3Smcr 	  maxbus = pci_bus_fixup(psc->sc_pc, 0);
643c34df0c3Smcr 	}
644c34df0c3Smcr 
64579770474Smsaitoh 	busdata = Cardbus_conf_read(ct, ca->ca_tag, PCI_BRIDGE_BUS_REG);
64679770474Smsaitoh 	if(PCI_BRIDGE_BUS_NUM_SECONDARY(busdata) == 0) {
647c0d1e7cbScegger 		aprint_error_dev(self, "still not configured, not fixable.\n");
648c34df0c3Smcr 		return;
649c34df0c3Smcr 	}
650c34df0c3Smcr 
651c34df0c3Smcr #if 0
65279770474Smsaitoh 	minbus = PCI_BRIDGE_BUS_NUM_SECONDARY(busdata);
65379770474Smsaitoh 	maxbus = PCI_BRIDGE_BUS_NUM_SUBORDINATE(busdata);
654c34df0c3Smcr #endif
655c34df0c3Smcr 
656c34df0c3Smcr 	/* now, go and assign addresses for the new devices */
657c34df0c3Smcr 	rbus_pci_addr_fixup(csc, cc, parent_sc,
658c34df0c3Smcr 			    psc->sc_pc,
659c34df0c3Smcr 			    ca,
660c34df0c3Smcr 			    minbus, maxbus);
661c34df0c3Smcr 
662c34df0c3Smcr 	/*
663c34df0c3Smcr 	 * now configure all connected devices to the IRQ which
664c34df0c3Smcr 	 * was assigned to this slot, as they will all arrive from
665c34df0c3Smcr 	 * that IRQ.
666c34df0c3Smcr 	 */
6671ca3ef38Sdrochner 	rbus_intr_fixup(psc->sc_pc, minbus, maxbus, 0);
668c34df0c3Smcr 
669c34df0c3Smcr 	/*
670c34df0c3Smcr 	 * enable direct routing of interrupts. We do this because
671c34df0c3Smcr 	 * we can not manage to get pccb_intr_establish() called until
672c34df0c3Smcr 	 * PCI subsystem is merged with rbus. The major thing that this
673c34df0c3Smcr 	 * routine does is avoid calling the driver's interrupt routine
674c34df0c3Smcr 	 * when the card has been removed.
675c34df0c3Smcr 	 *
676c34df0c3Smcr 	 * The rbus_ppb.c can not cope with card desertions until the merging
677c34df0c3Smcr 	 * anyway.
678c34df0c3Smcr 	 */
679c34df0c3Smcr 	pccbb_intr_route(psc);
680c34df0c3Smcr 
681c34df0c3Smcr 	/*
682c34df0c3Smcr 	 * Attach the PCI bus than hangs off of it.
683c34df0c3Smcr 	 *
684c34df0c3Smcr 	 * XXX Don't pass-through Memory Read Multiple.  Should we?
685c34df0c3Smcr 	 * XXX Consult the spec...
686c34df0c3Smcr 	 */
687c34df0c3Smcr 	pba.pba_iot  = ca->ca_iot;
688c34df0c3Smcr 	pba.pba_memt = ca->ca_memt;
689c34df0c3Smcr 	pba.pba_dmat = ca->ca_dmat;
690c34df0c3Smcr 	pba.pba_pc   = psc->sc_pc;
691a6b2b839Sdyoung 	pba.pba_flags    = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY;
69279770474Smsaitoh 	pba.pba_bus      = PCI_BRIDGE_BUS_NUM_SECONDARY(busdata);
693cfb25c83Slukem 	pba.pba_bridgetag = &csc->sc_tag;
694c34df0c3Smcr 	/*pba.pba_intrswiz = parent_sc->sc_intrswiz; */
695c34df0c3Smcr 	pba.pba_intrtag  = psc->sc_pa.pa_intrtag;
696c34df0c3Smcr 
697c7fb772bSthorpej 	config_found(self, &pba, rppbprint, CFARGS_NONE);
698c34df0c3Smcr }
699c34df0c3Smcr 
700c34df0c3Smcr int
ppb_activate(device_t self,enum devact act)701529e91fcScegger ppb_activate(device_t self, enum devact act)
702c34df0c3Smcr {
703c34df0c3Smcr   printf("ppb_activate called\n");
704c34df0c3Smcr   return 0;
705c34df0c3Smcr }
706