xref: /pciutils/lib/generic.c (revision eb620239)
1 /*
2  *	$Id: generic.c,v 1.8 2002/12/27 19:01:51 mj Exp $
3  *
4  *	The PCI Library -- Generic Direct Access Functions
5  *
6  *	Copyright (c) 1997--2000 Martin Mares <[email protected]>
7  *
8  *	Can be freely distributed and used under the terms of the GNU GPL.
9  */
10 
11 #include <string.h>
12 
13 #include "internal.h"
14 
15 void
16 pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
17 {
18   int dev, multi, ht;
19   struct pci_dev *t = pci_alloc_dev(a);
20 
21   a->debug("Scanning bus %02x for devices...\n", bus);
22   if (busmap[bus])
23     {
24       a->warning("Bus %02x seen twice (firmware bug). Ignored.", bus);
25       return;
26     }
27   busmap[bus] = 1;
28   t->bus = bus;
29   for(dev=0; dev<32; dev++)
30     {
31       t->dev = dev;
32       multi = 0;
33       for(t->func=0; !t->func || multi && t->func<8; t->func++)
34 	{
35 	  u32 vd = pci_read_long(t, PCI_VENDOR_ID);
36 	  struct pci_dev *d;
37 
38 	  if (!vd || vd == 0xffffffff)
39 	    continue;
40 	  ht = pci_read_byte(t, PCI_HEADER_TYPE);
41 	  if (!t->func)
42 	    multi = ht & 0x80;
43 	  ht &= 0x7f;
44 	  d = pci_alloc_dev(a);
45 	  d->bus = t->bus;
46 	  d->dev = t->dev;
47 	  d->func = t->func;
48 	  d->vendor_id = vd & 0xffff;
49 	  d->device_id = vd >> 16U;
50 	  d->known_fields = PCI_FILL_IDENT;
51 	  d->hdrtype = ht;
52 	  pci_link_dev(a, d);
53 	  switch (ht)
54 	    {
55 	    case PCI_HEADER_TYPE_NORMAL:
56 	      break;
57 	    case PCI_HEADER_TYPE_BRIDGE:
58 	    case PCI_HEADER_TYPE_CARDBUS:
59 	      pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS));
60 	      break;
61 	    default:
62 	      a->debug("Device %02x:%02x.%d has unknown header type %02x.\n", d->bus, d->dev, d->func, ht);
63 	    }
64 	}
65     }
66 }
67 
68 void
69 pci_generic_scan(struct pci_access *a)
70 {
71   byte busmap[256];
72 
73   bzero(busmap, sizeof(busmap));
74   pci_generic_scan_bus(a, busmap, 0);
75 }
76 
77 int
78 pci_generic_fill_info(struct pci_dev *d, int flags)
79 {
80   struct pci_access *a = d->access;
81 
82   if (flags & PCI_FILL_IDENT)
83     {
84       d->vendor_id = pci_read_word(d, PCI_VENDOR_ID);
85       d->device_id = pci_read_word(d, PCI_DEVICE_ID);
86     }
87   if (flags & PCI_FILL_IRQ)
88     d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE);
89   if (flags & PCI_FILL_BASES)
90     {
91       int cnt = 0, i;
92       bzero(d->base_addr, sizeof(d->base_addr));
93       switch (d->hdrtype)
94 	{
95 	case PCI_HEADER_TYPE_NORMAL:
96 	  cnt = 6;
97 	  break;
98 	case PCI_HEADER_TYPE_BRIDGE:
99 	  cnt = 2;
100 	  break;
101 	case PCI_HEADER_TYPE_CARDBUS:
102 	  cnt = 1;
103 	  break;
104 	}
105       if (cnt)
106 	{
107 	  u16 cmd = pci_read_word(d, PCI_COMMAND);
108 	  for(i=0; i<cnt; i++)
109 	    {
110 	      u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4);
111 	      if (!x || x == (u32) ~0)
112 		continue;
113 	      d->base_addr[i] = x;
114 	      if (x & PCI_BASE_ADDRESS_SPACE_IO)
115 		{
116 		  if (!a->buscentric && !(cmd & PCI_COMMAND_IO))
117 		    d->base_addr[i] = 0;
118 		}
119 	      else if (a->buscentric || (cmd & PCI_COMMAND_MEMORY))
120 		{
121 		  if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64)
122 		    {
123 		      if (i >= cnt-1)
124 			a->warning("%02x:%02x.%d: Invalid 64-bit address seen.", d->bus, d->dev, d->func);
125 		      else
126 			{
127 			  u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4);
128 #ifdef HAVE_64BIT_ADDRESS
129 			  d->base_addr[i-1] |= ((pciaddr_t) y) << 32;
130 #else
131 			  if (y)
132 			    {
133 			      a->warning("%02x:%02x.%d 64-bit device address ignored.", d->bus, d->dev, d->func);
134 			      d->base_addr[i-1] = 0;
135 			    }
136 #endif
137 			}
138 		    }
139 		}
140 	      else
141 		d->base_addr[i] = 0;
142 	    }
143 	}
144     }
145   if (flags & PCI_FILL_ROM_BASE)
146     {
147       int reg = 0;
148       d->rom_base_addr = 0;
149       switch (d->hdrtype)
150 	{
151 	case PCI_HEADER_TYPE_NORMAL:
152 	  reg = PCI_ROM_ADDRESS;
153 	  break;
154 	case PCI_HEADER_TYPE_BRIDGE:
155 	  reg = PCI_ROM_ADDRESS1;
156 	  break;
157 	}
158       if (reg)
159 	{
160 	  u32 a = pci_read_long(d, reg);
161 	  if (a & PCI_ROM_ADDRESS_ENABLE)
162 	    d->rom_base_addr = a;
163 	}
164     }
165   return flags & ~PCI_FILL_SIZES;
166 }
167 
168 static int
169 pci_generic_block_op(struct pci_dev *d, int pos, byte *buf, int len,
170 		 int (*r)(struct pci_dev *d, int pos, byte *buf, int len))
171 {
172   if ((pos & 1) && len >= 1)
173     {
174       if (!r(d, pos, buf, 1))
175 	return 0;
176       pos++; buf++; len--;
177     }
178   if ((pos & 3) && len >= 2)
179     {
180       if (!r(d, pos, buf, 2))
181 	return 0;
182       pos += 2; buf += 2; len -= 2;
183     }
184   while (len >= 4)
185     {
186       if (!r(d, pos, buf, 4))
187 	return 0;
188       pos += 4; buf += 4; len -= 4;
189     }
190   if (len >= 2)
191     {
192       if (!r(d, pos, buf, 2))
193 	return 0;
194       pos += 2; buf += 2; len -= 2;
195     }
196   if (len && !r(d, pos, buf, 1))
197     return 0;
198   return 1;
199 }
200 
201 int
202 pci_generic_block_read(struct pci_dev *d, int pos, byte *buf, int len)
203 {
204   return pci_generic_block_op(d, pos, buf, len, d->access->methods->read);
205 }
206 
207 int
208 pci_generic_block_write(struct pci_dev *d, int pos, byte *buf, int len)
209 {
210   return pci_generic_block_op(d, pos, buf, len, d->access->methods->write);
211 }
212