diff options
Diffstat (limited to 'drivers/pci/hotplug/shpchp_pci.c')
-rw-r--r-- | drivers/pci/hotplug/shpchp_pci.c | 314 |
1 files changed, 0 insertions, 314 deletions
diff --git a/drivers/pci/hotplug/shpchp_pci.c b/drivers/pci/hotplug/shpchp_pci.c index 6209972313f3..f51a97d7611f 100644 --- a/drivers/pci/hotplug/shpchp_pci.c +++ b/drivers/pci/hotplug/shpchp_pci.c | |||
@@ -166,317 +166,3 @@ int shpchp_unconfigure_device(struct pci_func* func) | |||
166 | return rc; | 166 | return rc; |
167 | } | 167 | } |
168 | 168 | ||
169 | /* More PCI configuration routines; this time centered around hotplug controller */ | ||
170 | |||
171 | |||
172 | /* | ||
173 | * shpchp_save_config | ||
174 | * | ||
175 | * Reads configuration for all slots in a PCI bus and saves info. | ||
176 | * | ||
177 | * Note: For non-hot plug busses, the slot # saved is the device # | ||
178 | * | ||
179 | * returns 0 if success | ||
180 | */ | ||
181 | int shpchp_save_config(struct controller *ctrl, int busnumber, int num_ctlr_slots, int first_device_num) | ||
182 | { | ||
183 | int rc; | ||
184 | u8 class_code; | ||
185 | u8 header_type; | ||
186 | u32 ID; | ||
187 | u8 secondary_bus; | ||
188 | struct pci_func *new_slot; | ||
189 | int sub_bus; | ||
190 | int FirstSupported; | ||
191 | int LastSupported; | ||
192 | int max_functions; | ||
193 | int function; | ||
194 | u8 DevError; | ||
195 | int device = 0; | ||
196 | int cloop = 0; | ||
197 | int stop_it; | ||
198 | int index; | ||
199 | int is_hot_plug = num_ctlr_slots || first_device_num; | ||
200 | struct pci_bus lpci_bus, *pci_bus; | ||
201 | |||
202 | dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, | ||
203 | num_ctlr_slots, first_device_num); | ||
204 | |||
205 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
206 | pci_bus = &lpci_bus; | ||
207 | |||
208 | dbg("%s: num_ctlr_slots = %d, first_device_num = %d\n", __FUNCTION__, | ||
209 | num_ctlr_slots, first_device_num); | ||
210 | |||
211 | /* Decide which slots are supported */ | ||
212 | if (is_hot_plug) { | ||
213 | /********************************* | ||
214 | * is_hot_plug is the slot mask | ||
215 | *********************************/ | ||
216 | FirstSupported = first_device_num; | ||
217 | LastSupported = FirstSupported + num_ctlr_slots - 1; | ||
218 | } else { | ||
219 | FirstSupported = 0; | ||
220 | LastSupported = 0x1F; | ||
221 | } | ||
222 | |||
223 | dbg("FirstSupported = %d, LastSupported = %d\n", FirstSupported, | ||
224 | LastSupported); | ||
225 | |||
226 | /* Save PCI configuration space for all devices in supported slots */ | ||
227 | pci_bus->number = busnumber; | ||
228 | for (device = FirstSupported; device <= LastSupported; device++) { | ||
229 | ID = 0xFFFFFFFF; | ||
230 | rc = pci_bus_read_config_dword(pci_bus, PCI_DEVFN(device, 0), | ||
231 | PCI_VENDOR_ID, &ID); | ||
232 | |||
233 | if (ID != 0xFFFFFFFF) { /* device in slot */ | ||
234 | rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), | ||
235 | 0x0B, &class_code); | ||
236 | if (rc) | ||
237 | return rc; | ||
238 | |||
239 | rc = pci_bus_read_config_byte(pci_bus, PCI_DEVFN(device, 0), | ||
240 | PCI_HEADER_TYPE, &header_type); | ||
241 | if (rc) | ||
242 | return rc; | ||
243 | |||
244 | dbg("class_code = %x, header_type = %x\n", class_code, header_type); | ||
245 | |||
246 | /* If multi-function device, set max_functions to 8 */ | ||
247 | if (header_type & 0x80) | ||
248 | max_functions = 8; | ||
249 | else | ||
250 | max_functions = 1; | ||
251 | |||
252 | function = 0; | ||
253 | |||
254 | do { | ||
255 | DevError = 0; | ||
256 | |||
257 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* P-P Bridge */ | ||
258 | /* Recurse the subordinate bus | ||
259 | * get the subordinate bus number | ||
260 | */ | ||
261 | rc = pci_bus_read_config_byte(pci_bus, | ||
262 | PCI_DEVFN(device, function), | ||
263 | PCI_SECONDARY_BUS, &secondary_bus); | ||
264 | if (rc) { | ||
265 | return rc; | ||
266 | } else { | ||
267 | sub_bus = (int) secondary_bus; | ||
268 | |||
269 | /* Save secondary bus cfg spc with this recursive call. */ | ||
270 | rc = shpchp_save_config(ctrl, sub_bus, 0, 0); | ||
271 | if (rc) | ||
272 | return rc; | ||
273 | } | ||
274 | } | ||
275 | |||
276 | index = 0; | ||
277 | new_slot = shpchp_slot_find(busnumber, device, index++); | ||
278 | |||
279 | dbg("new_slot = %p\n", new_slot); | ||
280 | |||
281 | while (new_slot && (new_slot->function != (u8) function)) { | ||
282 | new_slot = shpchp_slot_find(busnumber, device, index++); | ||
283 | dbg("new_slot = %p\n", new_slot); | ||
284 | } | ||
285 | if (!new_slot) { | ||
286 | /* Setup slot structure. */ | ||
287 | new_slot = shpchp_slot_create(busnumber); | ||
288 | dbg("new_slot = %p\n", new_slot); | ||
289 | |||
290 | if (new_slot == NULL) | ||
291 | return(1); | ||
292 | } | ||
293 | |||
294 | new_slot->bus = (u8) busnumber; | ||
295 | new_slot->device = (u8) device; | ||
296 | new_slot->function = (u8) function; | ||
297 | new_slot->is_a_board = 1; | ||
298 | new_slot->switch_save = 0x10; | ||
299 | new_slot->pwr_save = 1; | ||
300 | /* In case of unsupported board */ | ||
301 | new_slot->status = DevError; | ||
302 | new_slot->pci_dev = pci_find_slot(new_slot->bus, | ||
303 | (new_slot->device << 3) | new_slot->function); | ||
304 | dbg("new_slot->pci_dev = %p\n", new_slot->pci_dev); | ||
305 | |||
306 | for (cloop = 0; cloop < 0x20; cloop++) { | ||
307 | rc = pci_bus_read_config_dword(pci_bus, | ||
308 | PCI_DEVFN(device, function), | ||
309 | cloop << 2, | ||
310 | (u32 *) &(new_slot->config_space [cloop])); | ||
311 | /* dbg("new_slot->config_space[%x] = %x\n", | ||
312 | cloop, new_slot->config_space[cloop]); */ | ||
313 | if (rc) | ||
314 | return rc; | ||
315 | } | ||
316 | |||
317 | function++; | ||
318 | |||
319 | stop_it = 0; | ||
320 | |||
321 | /* this loop skips to the next present function | ||
322 | * reading in Class Code and Header type. | ||
323 | */ | ||
324 | |||
325 | while ((function < max_functions)&&(!stop_it)) { | ||
326 | rc = pci_bus_read_config_dword(pci_bus, | ||
327 | PCI_DEVFN(device, function), | ||
328 | PCI_VENDOR_ID, &ID); | ||
329 | |||
330 | if (ID == 0xFFFFFFFF) { /* nothing there. */ | ||
331 | function++; | ||
332 | dbg("Nothing there\n"); | ||
333 | } else { /* Something there */ | ||
334 | rc = pci_bus_read_config_byte(pci_bus, | ||
335 | PCI_DEVFN(device, function), | ||
336 | 0x0B, &class_code); | ||
337 | if (rc) | ||
338 | return rc; | ||
339 | |||
340 | rc = pci_bus_read_config_byte(pci_bus, | ||
341 | PCI_DEVFN(device, function), | ||
342 | PCI_HEADER_TYPE, &header_type); | ||
343 | if (rc) | ||
344 | return rc; | ||
345 | |||
346 | dbg("class_code = %x, header_type = %x\n", | ||
347 | class_code, header_type); | ||
348 | stop_it++; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | } while (function < max_functions); | ||
353 | /* End of IF (device in slot?) */ | ||
354 | } else if (is_hot_plug) { | ||
355 | /* Setup slot structure with entry for empty slot */ | ||
356 | new_slot = shpchp_slot_create(busnumber); | ||
357 | |||
358 | if (new_slot == NULL) { | ||
359 | return(1); | ||
360 | } | ||
361 | dbg("new_slot = %p\n", new_slot); | ||
362 | |||
363 | new_slot->bus = (u8) busnumber; | ||
364 | new_slot->device = (u8) device; | ||
365 | new_slot->function = 0; | ||
366 | new_slot->is_a_board = 0; | ||
367 | new_slot->presence_save = 0; | ||
368 | new_slot->switch_save = 0; | ||
369 | } | ||
370 | } /* End of FOR loop */ | ||
371 | |||
372 | return(0); | ||
373 | } | ||
374 | |||
375 | |||
376 | /* | ||
377 | * shpchp_save_slot_config | ||
378 | * | ||
379 | * Saves configuration info for all PCI devices in a given slot | ||
380 | * including subordinate busses. | ||
381 | * | ||
382 | * returns 0 if success | ||
383 | */ | ||
384 | int shpchp_save_slot_config(struct controller *ctrl, struct pci_func * new_slot) | ||
385 | { | ||
386 | int rc; | ||
387 | u8 class_code; | ||
388 | u8 header_type; | ||
389 | u32 ID; | ||
390 | u8 secondary_bus; | ||
391 | int sub_bus; | ||
392 | int max_functions; | ||
393 | int function; | ||
394 | int cloop = 0; | ||
395 | int stop_it; | ||
396 | struct pci_bus lpci_bus, *pci_bus; | ||
397 | memcpy(&lpci_bus, ctrl->pci_dev->subordinate, sizeof(lpci_bus)); | ||
398 | pci_bus = &lpci_bus; | ||
399 | pci_bus->number = new_slot->bus; | ||
400 | |||
401 | ID = 0xFFFFFFFF; | ||
402 | |||
403 | pci_bus_read_config_dword(pci_bus, PCI_DEVFN(new_slot->device, 0), | ||
404 | PCI_VENDOR_ID, &ID); | ||
405 | |||
406 | if (ID != 0xFFFFFFFF) { /* device in slot */ | ||
407 | pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), | ||
408 | 0x0B, &class_code); | ||
409 | |||
410 | pci_bus_read_config_byte(pci_bus, PCI_DEVFN(new_slot->device, 0), | ||
411 | PCI_HEADER_TYPE, &header_type); | ||
412 | |||
413 | if (header_type & 0x80) /* Multi-function device */ | ||
414 | max_functions = 8; | ||
415 | else | ||
416 | max_functions = 1; | ||
417 | |||
418 | function = 0; | ||
419 | |||
420 | do { | ||
421 | if ((header_type & 0x7F) == PCI_HEADER_TYPE_BRIDGE) { /* PCI-PCI Bridge */ | ||
422 | /* Recurse the subordinate bus */ | ||
423 | pci_bus_read_config_byte(pci_bus, | ||
424 | PCI_DEVFN(new_slot->device, function), | ||
425 | PCI_SECONDARY_BUS, &secondary_bus); | ||
426 | |||
427 | sub_bus = (int) secondary_bus; | ||
428 | |||
429 | /* Save the config headers for the secondary bus. */ | ||
430 | rc = shpchp_save_config(ctrl, sub_bus, 0, 0); | ||
431 | |||
432 | if (rc) | ||
433 | return rc; | ||
434 | |||
435 | } /* End of IF */ | ||
436 | |||
437 | new_slot->status = 0; | ||
438 | |||
439 | for (cloop = 0; cloop < 0x20; cloop++) { | ||
440 | pci_bus_read_config_dword(pci_bus, | ||
441 | PCI_DEVFN(new_slot->device, function), | ||
442 | cloop << 2, | ||
443 | (u32 *) &(new_slot->config_space [cloop])); | ||
444 | } | ||
445 | |||
446 | function++; | ||
447 | |||
448 | stop_it = 0; | ||
449 | |||
450 | /* this loop skips to the next present function | ||
451 | * reading in the Class Code and the Header type. | ||
452 | */ | ||
453 | |||
454 | while ((function < max_functions) && (!stop_it)) { | ||
455 | pci_bus_read_config_dword(pci_bus, | ||
456 | PCI_DEVFN(new_slot->device, function), | ||
457 | PCI_VENDOR_ID, &ID); | ||
458 | |||
459 | if (ID == 0xFFFFFFFF) { /* nothing there. */ | ||
460 | function++; | ||
461 | } else { /* Something there */ | ||
462 | pci_bus_read_config_byte(pci_bus, | ||
463 | PCI_DEVFN(new_slot->device, function), | ||
464 | 0x0B, &class_code); | ||
465 | |||
466 | pci_bus_read_config_byte(pci_bus, | ||
467 | PCI_DEVFN(new_slot->device, function), | ||
468 | PCI_HEADER_TYPE, &header_type); | ||
469 | |||
470 | stop_it++; | ||
471 | } | ||
472 | } | ||
473 | |||
474 | } while (function < max_functions); | ||
475 | } /* End of IF (device in slot?) */ | ||
476 | else { | ||
477 | return 2; | ||
478 | } | ||
479 | |||
480 | return 0; | ||
481 | } | ||
482 | |||