xref: /aosp_15_r20/external/pciutils/lib/emulated.c (revision c2e0c6b56a71da9abe8df5c8348fb3eb5c2c9251)
1*c2e0c6b5SAndroid Build Coastguard Worker /*
2*c2e0c6b5SAndroid Build Coastguard Worker  *	The PCI Library -- Virtual Emulated Config Space Access Functions
3*c2e0c6b5SAndroid Build Coastguard Worker  *
4*c2e0c6b5SAndroid Build Coastguard Worker  *	Copyright (c) 2022 Pali Rohár
5*c2e0c6b5SAndroid Build Coastguard Worker  *
6*c2e0c6b5SAndroid Build Coastguard Worker  *	Can be freely distributed and used under the terms of the GNU GPL v2+.
7*c2e0c6b5SAndroid Build Coastguard Worker  *
8*c2e0c6b5SAndroid Build Coastguard Worker  *	SPDX-License-Identifier: GPL-2.0-or-later
9*c2e0c6b5SAndroid Build Coastguard Worker  */
10*c2e0c6b5SAndroid Build Coastguard Worker 
11*c2e0c6b5SAndroid Build Coastguard Worker #include "internal.h"
12*c2e0c6b5SAndroid Build Coastguard Worker 
13*c2e0c6b5SAndroid Build Coastguard Worker static u32
ioflg_to_pciflg(pciaddr_t ioflg)14*c2e0c6b5SAndroid Build Coastguard Worker ioflg_to_pciflg(pciaddr_t ioflg)
15*c2e0c6b5SAndroid Build Coastguard Worker {
16*c2e0c6b5SAndroid Build Coastguard Worker   u32 flg = 0;
17*c2e0c6b5SAndroid Build Coastguard Worker 
18*c2e0c6b5SAndroid Build Coastguard Worker   if ((ioflg & PCI_IORESOURCE_TYPE_BITS) == PCI_IORESOURCE_IO)
19*c2e0c6b5SAndroid Build Coastguard Worker     flg = PCI_BASE_ADDRESS_SPACE_IO;
20*c2e0c6b5SAndroid Build Coastguard Worker   else if ((ioflg & PCI_IORESOURCE_TYPE_BITS) == PCI_IORESOURCE_MEM)
21*c2e0c6b5SAndroid Build Coastguard Worker     {
22*c2e0c6b5SAndroid Build Coastguard Worker       flg = PCI_BASE_ADDRESS_SPACE_MEMORY;
23*c2e0c6b5SAndroid Build Coastguard Worker       if (ioflg & PCI_IORESOURCE_MEM_64)
24*c2e0c6b5SAndroid Build Coastguard Worker         flg |= PCI_BASE_ADDRESS_MEM_TYPE_64;
25*c2e0c6b5SAndroid Build Coastguard Worker       else
26*c2e0c6b5SAndroid Build Coastguard Worker         flg |= PCI_BASE_ADDRESS_MEM_TYPE_32;
27*c2e0c6b5SAndroid Build Coastguard Worker       if (ioflg & PCI_IORESOURCE_PREFETCH)
28*c2e0c6b5SAndroid Build Coastguard Worker         flg |= PCI_BASE_ADDRESS_MEM_PREFETCH;
29*c2e0c6b5SAndroid Build Coastguard Worker     }
30*c2e0c6b5SAndroid Build Coastguard Worker 
31*c2e0c6b5SAndroid Build Coastguard Worker   return flg;
32*c2e0c6b5SAndroid Build Coastguard Worker }
33*c2e0c6b5SAndroid Build Coastguard Worker 
34*c2e0c6b5SAndroid Build Coastguard Worker static u32
baseres_to_pcires(pciaddr_t addr,pciaddr_t ioflg,int * have_sec,u32 * sec_val)35*c2e0c6b5SAndroid Build Coastguard Worker baseres_to_pcires(pciaddr_t addr, pciaddr_t ioflg, int *have_sec, u32 *sec_val)
36*c2e0c6b5SAndroid Build Coastguard Worker {
37*c2e0c6b5SAndroid Build Coastguard Worker   u32 val = ioflg_to_pciflg(ioflg);
38*c2e0c6b5SAndroid Build Coastguard Worker 
39*c2e0c6b5SAndroid Build Coastguard Worker   if (have_sec)
40*c2e0c6b5SAndroid Build Coastguard Worker     *have_sec = 0;
41*c2e0c6b5SAndroid Build Coastguard Worker 
42*c2e0c6b5SAndroid Build Coastguard Worker   if ((val & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO && addr <= 0xffffffff)
43*c2e0c6b5SAndroid Build Coastguard Worker     val |= addr & PCI_BASE_ADDRESS_IO_MASK;
44*c2e0c6b5SAndroid Build Coastguard Worker   else if ((val & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
45*c2e0c6b5SAndroid Build Coastguard Worker     {
46*c2e0c6b5SAndroid Build Coastguard Worker       val |= addr & PCI_BASE_ADDRESS_MEM_MASK;
47*c2e0c6b5SAndroid Build Coastguard Worker       if ((val & PCI_BASE_ADDRESS_MEM_TYPE_64) && have_sec)
48*c2e0c6b5SAndroid Build Coastguard Worker         {
49*c2e0c6b5SAndroid Build Coastguard Worker           *have_sec = 1;
50*c2e0c6b5SAndroid Build Coastguard Worker           *sec_val = addr >> 32;
51*c2e0c6b5SAndroid Build Coastguard Worker         }
52*c2e0c6b5SAndroid Build Coastguard Worker     }
53*c2e0c6b5SAndroid Build Coastguard Worker 
54*c2e0c6b5SAndroid Build Coastguard Worker   return val;
55*c2e0c6b5SAndroid Build Coastguard Worker }
56*c2e0c6b5SAndroid Build Coastguard Worker 
57*c2e0c6b5SAndroid Build Coastguard Worker static inline u32
even_baseres_to_pcires(pciaddr_t addr,pciaddr_t ioflg)58*c2e0c6b5SAndroid Build Coastguard Worker even_baseres_to_pcires(pciaddr_t addr, pciaddr_t ioflg)
59*c2e0c6b5SAndroid Build Coastguard Worker {
60*c2e0c6b5SAndroid Build Coastguard Worker   return baseres_to_pcires(addr, ioflg, NULL, NULL);
61*c2e0c6b5SAndroid Build Coastguard Worker }
62*c2e0c6b5SAndroid Build Coastguard Worker 
63*c2e0c6b5SAndroid Build Coastguard Worker static inline u32
odd_baseres_to_pcires(pciaddr_t addr0,pciaddr_t ioflg0,pciaddr_t addr,pciaddr_t ioflg)64*c2e0c6b5SAndroid Build Coastguard Worker odd_baseres_to_pcires(pciaddr_t addr0, pciaddr_t ioflg0, pciaddr_t addr, pciaddr_t ioflg)
65*c2e0c6b5SAndroid Build Coastguard Worker {
66*c2e0c6b5SAndroid Build Coastguard Worker   int have_sec;
67*c2e0c6b5SAndroid Build Coastguard Worker   u32 val;
68*c2e0c6b5SAndroid Build Coastguard Worker   baseres_to_pcires(addr0, ioflg0, &have_sec, &val);
69*c2e0c6b5SAndroid Build Coastguard Worker   if (!have_sec)
70*c2e0c6b5SAndroid Build Coastguard Worker     val = baseres_to_pcires(addr, ioflg, NULL, NULL);
71*c2e0c6b5SAndroid Build Coastguard Worker   return val;
72*c2e0c6b5SAndroid Build Coastguard Worker }
73*c2e0c6b5SAndroid Build Coastguard Worker 
74*c2e0c6b5SAndroid Build Coastguard Worker int
pci_emulated_read(struct pci_dev * d,int pos,byte * buf,int len)75*c2e0c6b5SAndroid Build Coastguard Worker pci_emulated_read(struct pci_dev *d, int pos, byte *buf, int len)
76*c2e0c6b5SAndroid Build Coastguard Worker {
77*c2e0c6b5SAndroid Build Coastguard Worker   u32 ht = PCI_HEADER_TYPE_NORMAL;
78*c2e0c6b5SAndroid Build Coastguard Worker   u32 val = 0;
79*c2e0c6b5SAndroid Build Coastguard Worker   int i;
80*c2e0c6b5SAndroid Build Coastguard Worker 
81*c2e0c6b5SAndroid Build Coastguard Worker   if (pos >= 64)
82*c2e0c6b5SAndroid Build Coastguard Worker     return 0;
83*c2e0c6b5SAndroid Build Coastguard Worker 
84*c2e0c6b5SAndroid Build Coastguard Worker   if (len > 4)
85*c2e0c6b5SAndroid Build Coastguard Worker     return pci_generic_block_read(d, pos, buf, len);
86*c2e0c6b5SAndroid Build Coastguard Worker 
87*c2e0c6b5SAndroid Build Coastguard Worker   if (d->device_class == PCI_CLASS_BRIDGE_PCI)
88*c2e0c6b5SAndroid Build Coastguard Worker     ht = PCI_HEADER_TYPE_BRIDGE;
89*c2e0c6b5SAndroid Build Coastguard Worker   else if (d->device_class == PCI_CLASS_BRIDGE_CARDBUS)
90*c2e0c6b5SAndroid Build Coastguard Worker     ht = PCI_HEADER_TYPE_CARDBUS;
91*c2e0c6b5SAndroid Build Coastguard Worker 
92*c2e0c6b5SAndroid Build Coastguard Worker   switch (pos & ~3)
93*c2e0c6b5SAndroid Build Coastguard Worker     {
94*c2e0c6b5SAndroid Build Coastguard Worker       case PCI_COMMAND:
95*c2e0c6b5SAndroid Build Coastguard Worker         for (i = 0; i < 6; i++)
96*c2e0c6b5SAndroid Build Coastguard Worker           {
97*c2e0c6b5SAndroid Build Coastguard Worker             if (!d->size[i])
98*c2e0c6b5SAndroid Build Coastguard Worker               continue;
99*c2e0c6b5SAndroid Build Coastguard Worker             if ((d->flags[i] & PCI_IORESOURCE_TYPE_BITS) == PCI_IORESOURCE_IO)
100*c2e0c6b5SAndroid Build Coastguard Worker               val |= PCI_COMMAND_IO;
101*c2e0c6b5SAndroid Build Coastguard Worker             else if ((d->flags[i] & PCI_IORESOURCE_TYPE_BITS) == PCI_IORESOURCE_MEM)
102*c2e0c6b5SAndroid Build Coastguard Worker               val |= PCI_COMMAND_MEMORY;
103*c2e0c6b5SAndroid Build Coastguard Worker           }
104*c2e0c6b5SAndroid Build Coastguard Worker         break;
105*c2e0c6b5SAndroid Build Coastguard Worker       case PCI_VENDOR_ID:
106*c2e0c6b5SAndroid Build Coastguard Worker         val = (d->device_id << 16) | d->vendor_id;
107*c2e0c6b5SAndroid Build Coastguard Worker         break;
108*c2e0c6b5SAndroid Build Coastguard Worker       case PCI_CLASS_REVISION:
109*c2e0c6b5SAndroid Build Coastguard Worker         val = (d->device_class << 16) | (d->prog_if << 8) | d->rev_id;
110*c2e0c6b5SAndroid Build Coastguard Worker         break;
111*c2e0c6b5SAndroid Build Coastguard Worker       case PCI_CACHE_LINE_SIZE:
112*c2e0c6b5SAndroid Build Coastguard Worker         val = ht << 16;
113*c2e0c6b5SAndroid Build Coastguard Worker         break;
114*c2e0c6b5SAndroid Build Coastguard Worker       case PCI_BASE_ADDRESS_0:
115*c2e0c6b5SAndroid Build Coastguard Worker         val = even_baseres_to_pcires(d->base_addr[0], d->flags[0]);
116*c2e0c6b5SAndroid Build Coastguard Worker         break;
117*c2e0c6b5SAndroid Build Coastguard Worker       case PCI_INTERRUPT_LINE:
118*c2e0c6b5SAndroid Build Coastguard Worker         val = (d->irq >= 0 && d->irq <= 0xff) ? d->irq : 0;
119*c2e0c6b5SAndroid Build Coastguard Worker         break;
120*c2e0c6b5SAndroid Build Coastguard Worker     }
121*c2e0c6b5SAndroid Build Coastguard Worker 
122*c2e0c6b5SAndroid Build Coastguard Worker   if ((pos & ~3) == PCI_BASE_ADDRESS_1 && (ht == PCI_HEADER_TYPE_NORMAL || ht == PCI_HEADER_TYPE_BRIDGE))
123*c2e0c6b5SAndroid Build Coastguard Worker     val = odd_baseres_to_pcires(d->base_addr[0], d->flags[0], d->base_addr[1], d->flags[1]);
124*c2e0c6b5SAndroid Build Coastguard Worker 
125*c2e0c6b5SAndroid Build Coastguard Worker   if (ht == PCI_HEADER_TYPE_NORMAL)
126*c2e0c6b5SAndroid Build Coastguard Worker     switch (pos & ~3)
127*c2e0c6b5SAndroid Build Coastguard Worker       {
128*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_BASE_ADDRESS_2:
129*c2e0c6b5SAndroid Build Coastguard Worker           val = even_baseres_to_pcires(d->base_addr[2], d->flags[2]);
130*c2e0c6b5SAndroid Build Coastguard Worker           break;
131*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_BASE_ADDRESS_3:
132*c2e0c6b5SAndroid Build Coastguard Worker           val = odd_baseres_to_pcires(d->base_addr[2], d->flags[2], d->base_addr[3], d->flags[3]);
133*c2e0c6b5SAndroid Build Coastguard Worker           break;
134*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_BASE_ADDRESS_4:
135*c2e0c6b5SAndroid Build Coastguard Worker           val = even_baseres_to_pcires(d->base_addr[4], d->flags[4]);
136*c2e0c6b5SAndroid Build Coastguard Worker           break;
137*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_BASE_ADDRESS_5:
138*c2e0c6b5SAndroid Build Coastguard Worker           val = odd_baseres_to_pcires(d->base_addr[4], d->flags[4], d->base_addr[5], d->flags[5]);
139*c2e0c6b5SAndroid Build Coastguard Worker           break;
140*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_SUBSYSTEM_VENDOR_ID:
141*c2e0c6b5SAndroid Build Coastguard Worker           val = (d->subsys_id << 16) | d->subsys_vendor_id;
142*c2e0c6b5SAndroid Build Coastguard Worker           break;
143*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_ROM_ADDRESS:
144*c2e0c6b5SAndroid Build Coastguard Worker           val = d->rom_base_addr & PCI_ROM_ADDRESS_MASK;
145*c2e0c6b5SAndroid Build Coastguard Worker           if (val)
146*c2e0c6b5SAndroid Build Coastguard Worker             val |= PCI_ROM_ADDRESS_ENABLE;
147*c2e0c6b5SAndroid Build Coastguard Worker           break;
148*c2e0c6b5SAndroid Build Coastguard Worker       }
149*c2e0c6b5SAndroid Build Coastguard Worker   else if (ht == PCI_HEADER_TYPE_BRIDGE)
150*c2e0c6b5SAndroid Build Coastguard Worker     switch (pos & ~3)
151*c2e0c6b5SAndroid Build Coastguard Worker       {
152*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_COMMAND:
153*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[0])
154*c2e0c6b5SAndroid Build Coastguard Worker             val |= PCI_COMMAND_IO;
155*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[1] || d->bridge_size[2])
156*c2e0c6b5SAndroid Build Coastguard Worker             val |= PCI_COMMAND_MEMORY;
157*c2e0c6b5SAndroid Build Coastguard Worker           break;
158*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_PRIMARY_BUS:
159*c2e0c6b5SAndroid Build Coastguard Worker           val = d->bus;
160*c2e0c6b5SAndroid Build Coastguard Worker           break;
161*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_IO_BASE:
162*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[0])
163*c2e0c6b5SAndroid Build Coastguard Worker             {
164*c2e0c6b5SAndroid Build Coastguard Worker               val = (((((d->bridge_base_addr[0] + d->bridge_size[0] - 1) >> 8) & PCI_IO_RANGE_MASK) << 8) & 0xff00) |
165*c2e0c6b5SAndroid Build Coastguard Worker                     (((d->bridge_base_addr[0] >> 8) & PCI_IO_RANGE_MASK) & 0x00ff);
166*c2e0c6b5SAndroid Build Coastguard Worker               if ((d->bridge_flags[0] & PCI_IORESOURCE_IO_16BIT_ADDR) &&
167*c2e0c6b5SAndroid Build Coastguard Worker                   d->bridge_base_addr[0] + d->bridge_size[0] - 1 <= 0xffff)
168*c2e0c6b5SAndroid Build Coastguard Worker                 val |= (PCI_IO_RANGE_TYPE_16 << 8) | PCI_IO_RANGE_TYPE_16;
169*c2e0c6b5SAndroid Build Coastguard Worker               else
170*c2e0c6b5SAndroid Build Coastguard Worker                 val |= (PCI_IO_RANGE_TYPE_32 << 8) | PCI_IO_RANGE_TYPE_32;
171*c2e0c6b5SAndroid Build Coastguard Worker             }
172*c2e0c6b5SAndroid Build Coastguard Worker           else
173*c2e0c6b5SAndroid Build Coastguard Worker             val = 0xff & PCI_IO_RANGE_MASK;
174*c2e0c6b5SAndroid Build Coastguard Worker           break;
175*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_MEMORY_BASE:
176*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[1])
177*c2e0c6b5SAndroid Build Coastguard Worker             val = (((((d->bridge_base_addr[1] + d->bridge_size[1] - 1) >> 16) & PCI_MEMORY_RANGE_MASK) << 16) & 0xffff0000) |
178*c2e0c6b5SAndroid Build Coastguard Worker                   (((d->bridge_base_addr[1] >> 16) & PCI_MEMORY_RANGE_MASK) & 0x0000ffff);
179*c2e0c6b5SAndroid Build Coastguard Worker           else
180*c2e0c6b5SAndroid Build Coastguard Worker             val = 0xffff & PCI_MEMORY_RANGE_MASK;
181*c2e0c6b5SAndroid Build Coastguard Worker           break;
182*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_PREF_MEMORY_BASE:
183*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[2])
184*c2e0c6b5SAndroid Build Coastguard Worker             {
185*c2e0c6b5SAndroid Build Coastguard Worker               val = (((((d->bridge_base_addr[2] + d->bridge_size[2] - 1) >> 16) & PCI_PREF_RANGE_MASK) << 16) & 0xffff0000) |
186*c2e0c6b5SAndroid Build Coastguard Worker                     (((d->bridge_base_addr[2] >> 16) & PCI_PREF_RANGE_MASK) & 0x0000ffff);
187*c2e0c6b5SAndroid Build Coastguard Worker               if ((d->bridge_flags[2] & PCI_IORESOURCE_MEM_64) ||
188*c2e0c6b5SAndroid Build Coastguard Worker                   d->bridge_base_addr[2] + d->bridge_size[2] - 1 > 0xffffffff)
189*c2e0c6b5SAndroid Build Coastguard Worker                 val |= (PCI_PREF_RANGE_TYPE_64 << 16) | PCI_PREF_RANGE_TYPE_64;
190*c2e0c6b5SAndroid Build Coastguard Worker               else
191*c2e0c6b5SAndroid Build Coastguard Worker                 val |= (PCI_PREF_RANGE_TYPE_32 << 16) | PCI_PREF_RANGE_TYPE_32;
192*c2e0c6b5SAndroid Build Coastguard Worker             }
193*c2e0c6b5SAndroid Build Coastguard Worker           else
194*c2e0c6b5SAndroid Build Coastguard Worker             val = 0xffff & PCI_PREF_RANGE_MASK;
195*c2e0c6b5SAndroid Build Coastguard Worker           break;
196*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_PREF_BASE_UPPER32:
197*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[2])
198*c2e0c6b5SAndroid Build Coastguard Worker             val = d->bridge_base_addr[2] >> 32;
199*c2e0c6b5SAndroid Build Coastguard Worker           break;
200*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_PREF_LIMIT_UPPER32:
201*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[2])
202*c2e0c6b5SAndroid Build Coastguard Worker             val = (d->bridge_base_addr[2] + d->bridge_size[2] - 1) >> 32;
203*c2e0c6b5SAndroid Build Coastguard Worker           break;
204*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_IO_BASE_UPPER16:
205*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[0])
206*c2e0c6b5SAndroid Build Coastguard Worker             val = ((((d->bridge_base_addr[0] + d->bridge_size[0] - 1) >> 16) << 16) & 0xffff0000) |
207*c2e0c6b5SAndroid Build Coastguard Worker                   ((d->bridge_base_addr[0] >> 16) & 0x0000ffff);
208*c2e0c6b5SAndroid Build Coastguard Worker           break;
209*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_ROM_ADDRESS1:
210*c2e0c6b5SAndroid Build Coastguard Worker           val = d->rom_base_addr & PCI_ROM_ADDRESS_MASK;
211*c2e0c6b5SAndroid Build Coastguard Worker           if (val)
212*c2e0c6b5SAndroid Build Coastguard Worker             val |= PCI_ROM_ADDRESS_ENABLE;
213*c2e0c6b5SAndroid Build Coastguard Worker           break;
214*c2e0c6b5SAndroid Build Coastguard Worker       }
215*c2e0c6b5SAndroid Build Coastguard Worker   else if (ht == PCI_HEADER_TYPE_CARDBUS)
216*c2e0c6b5SAndroid Build Coastguard Worker     switch (pos & ~3)
217*c2e0c6b5SAndroid Build Coastguard Worker       {
218*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_COMMAND:
219*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[0] || d->bridge_size[1])
220*c2e0c6b5SAndroid Build Coastguard Worker             val |= PCI_COMMAND_MEMORY;
221*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[2] || d->bridge_size[3])
222*c2e0c6b5SAndroid Build Coastguard Worker             val |= PCI_COMMAND_IO;
223*c2e0c6b5SAndroid Build Coastguard Worker           break;
224*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_CB_PRIMARY_BUS:
225*c2e0c6b5SAndroid Build Coastguard Worker           val = d->bus;
226*c2e0c6b5SAndroid Build Coastguard Worker           break;
227*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_CB_MEMORY_BASE_0:
228*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[0])
229*c2e0c6b5SAndroid Build Coastguard Worker             val = d->bridge_base_addr[0] & ~0xfff;
230*c2e0c6b5SAndroid Build Coastguard Worker           else
231*c2e0c6b5SAndroid Build Coastguard Worker             val = 0xffffffff & ~0xfff;
232*c2e0c6b5SAndroid Build Coastguard Worker           break;
233*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_CB_MEMORY_LIMIT_0:
234*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[0])
235*c2e0c6b5SAndroid Build Coastguard Worker             val = (d->bridge_base_addr[0] + d->bridge_size[0] - 1) & ~0xfff;
236*c2e0c6b5SAndroid Build Coastguard Worker           break;
237*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_CB_MEMORY_BASE_1:
238*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[1])
239*c2e0c6b5SAndroid Build Coastguard Worker             val = d->bridge_base_addr[1] & ~0xfff;
240*c2e0c6b5SAndroid Build Coastguard Worker           else
241*c2e0c6b5SAndroid Build Coastguard Worker             val = 0xffffffff & ~0xfff;
242*c2e0c6b5SAndroid Build Coastguard Worker           break;
243*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_CB_MEMORY_LIMIT_1:
244*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[1])
245*c2e0c6b5SAndroid Build Coastguard Worker             val = (d->bridge_base_addr[1] + d->bridge_size[1] - 1) & ~0xfff;
246*c2e0c6b5SAndroid Build Coastguard Worker           break;
247*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_CB_IO_BASE_0:
248*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[2])
249*c2e0c6b5SAndroid Build Coastguard Worker             {
250*c2e0c6b5SAndroid Build Coastguard Worker               val = d->bridge_base_addr[2] & PCI_CB_IO_RANGE_MASK;
251*c2e0c6b5SAndroid Build Coastguard Worker               if ((d->bridge_flags[2] & PCI_IORESOURCE_IO_16BIT_ADDR) ||
252*c2e0c6b5SAndroid Build Coastguard Worker                   d->bridge_base_addr[2] + d->bridge_size[2] - 1 <= 0xffff)
253*c2e0c6b5SAndroid Build Coastguard Worker                 val |= PCI_IO_RANGE_TYPE_16;
254*c2e0c6b5SAndroid Build Coastguard Worker               else
255*c2e0c6b5SAndroid Build Coastguard Worker                 val |= PCI_IO_RANGE_TYPE_32;
256*c2e0c6b5SAndroid Build Coastguard Worker             }
257*c2e0c6b5SAndroid Build Coastguard Worker           else
258*c2e0c6b5SAndroid Build Coastguard Worker             val = 0x0000ffff & PCI_CB_IO_RANGE_MASK;
259*c2e0c6b5SAndroid Build Coastguard Worker           break;
260*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_CB_IO_LIMIT_0:
261*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[2])
262*c2e0c6b5SAndroid Build Coastguard Worker             val = (d->bridge_base_addr[2] + d->bridge_size[2] - 1) & PCI_CB_IO_RANGE_MASK;
263*c2e0c6b5SAndroid Build Coastguard Worker           break;
264*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_CB_IO_BASE_1:
265*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[3])
266*c2e0c6b5SAndroid Build Coastguard Worker             {
267*c2e0c6b5SAndroid Build Coastguard Worker               val = d->bridge_base_addr[3] & PCI_CB_IO_RANGE_MASK;
268*c2e0c6b5SAndroid Build Coastguard Worker               if ((d->bridge_flags[3] & PCI_IORESOURCE_IO_16BIT_ADDR) ||
269*c2e0c6b5SAndroid Build Coastguard Worker                   d->bridge_base_addr[3] + d->bridge_size[3] - 1 <= 0xffff)
270*c2e0c6b5SAndroid Build Coastguard Worker                 val |= PCI_IO_RANGE_TYPE_16;
271*c2e0c6b5SAndroid Build Coastguard Worker               else
272*c2e0c6b5SAndroid Build Coastguard Worker                 val |= PCI_IO_RANGE_TYPE_32;
273*c2e0c6b5SAndroid Build Coastguard Worker             }
274*c2e0c6b5SAndroid Build Coastguard Worker           else
275*c2e0c6b5SAndroid Build Coastguard Worker             val = 0x0000ffff & PCI_CB_IO_RANGE_MASK;
276*c2e0c6b5SAndroid Build Coastguard Worker           break;
277*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_CB_IO_LIMIT_1:
278*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_size[3])
279*c2e0c6b5SAndroid Build Coastguard Worker             val = (d->bridge_base_addr[3] + d->bridge_size[3] - 1) & PCI_CB_IO_RANGE_MASK;
280*c2e0c6b5SAndroid Build Coastguard Worker           break;
281*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_CB_BRIDGE_CONTROL:
282*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_flags[0] & PCI_IORESOURCE_PREFETCH)
283*c2e0c6b5SAndroid Build Coastguard Worker             val |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
284*c2e0c6b5SAndroid Build Coastguard Worker           if (d->bridge_flags[1] & PCI_IORESOURCE_PREFETCH)
285*c2e0c6b5SAndroid Build Coastguard Worker             val |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM1;
286*c2e0c6b5SAndroid Build Coastguard Worker           break;
287*c2e0c6b5SAndroid Build Coastguard Worker         case PCI_CB_SUBSYSTEM_VENDOR_ID:
288*c2e0c6b5SAndroid Build Coastguard Worker           val = (d->subsys_id << 16) | d->subsys_vendor_id;
289*c2e0c6b5SAndroid Build Coastguard Worker           break;
290*c2e0c6b5SAndroid Build Coastguard Worker       }
291*c2e0c6b5SAndroid Build Coastguard Worker 
292*c2e0c6b5SAndroid Build Coastguard Worker   if (len <= 2)
293*c2e0c6b5SAndroid Build Coastguard Worker     val = (val >> (8 * (pos & 3))) & ((1 << (len * 8)) - 1);
294*c2e0c6b5SAndroid Build Coastguard Worker 
295*c2e0c6b5SAndroid Build Coastguard Worker   while (len-- > 0)
296*c2e0c6b5SAndroid Build Coastguard Worker     {
297*c2e0c6b5SAndroid Build Coastguard Worker       *(buf++) = val & 0xff;
298*c2e0c6b5SAndroid Build Coastguard Worker       val >>= 8;
299*c2e0c6b5SAndroid Build Coastguard Worker     }
300*c2e0c6b5SAndroid Build Coastguard Worker   return 1;
301*c2e0c6b5SAndroid Build Coastguard Worker }
302