--- /dev/null Wed Dec 31 16:00:00 1969 +++ b/drivers/hotplug/ppcphp.c Fri Mar 19 09:50:42 2004 @@ -0,0 +1,237 @@ + +> - Port the Linux PPC hotplug pci controller driver to the +> hotplug pci core interface, whenever Anton sends me an +> updated file... + +OK, OK :) + +I actually started rewriting the ppc hotswap code, it was a mess :) +I found yet another useful bit of information, we can get the type +of the pci slot. + +It is missing some of the insert and remove hooks, turns out we have an +issue with large memory machines that means Im going to have to rewrite +that bit totally. So there are some bits missing but it should end up +fitting inside these hooks. + +Any suggestions on how to integrate it would be appreciated, I bundled a +few things together into a struct Foo in the hope you would have +somewhere to put them :) + +Anton + + +/* + * Copyright (C) 2001 Anton Blanchard , IBM + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include + +#define DR_INDICATOR 9002 +#define DR_ENTITY_SENSE 9003 +#define POWER_FULL_ON 100 +#define POWER_FULL_OFF 0 +#define ISOLATION_STATE 9001 +#define ISOLATE 0 +#define UNISOLATE 1 + +char ibm_types[] = { + "NULL", + "33Mhz, 32 bit, 5 Volt PCI", + "50Mhz, 32 bit, 5 Volt PCI", + "33Mhz, 32 bit, 3.3 Volt PCI", + "33Mhz, 64 bit, 5 Volt PCI", + "50Mhz, 64 bit, 5 Volt PCI", + "33Mhz, 64 bit, 3.3 Volt PCI", + "66Mhz, 32 bit, 3.3 Volt PCI", + "66Mhz, 64 bit, 3.3 Volt PCI", + "Remote I/O (RIO), copper", + "Remote I/O (RIO), fibre optic" +}; + +struct Foo { + int state; + int type; + int power_domain; + char *name; +}; + +char *get_type(struct Foo *foo) +{ + return ibm_types[foo->type]; +} + +int get_state(struct Foo *foo) +{ + int error; + long status; + + error = call_rtas("get-sensor-state", 2, 2, &status, DR_ENTITY_SENSE, + index[1]); + + /* + * status: + * 0 - Slot is empty + * 1 - Slot is occupied + * 2 - Slot is unusable + * + * error: + * -9000 - Slot must be power up and unisolated to get state + * -9001 - Slot must be powerd up to get state + * -9002 - Slot is unusable + */ + if (error == -9000) + status = 3; + else if (error == -9001) + status = 3; + else if (error == -9002) + status = 2; + else if (error) + status = -1; + + return status; +} + +int set_indicator(struct Foo *foo, int state) +{ + int error; + + /* + * 0 - Inactive + * 1 - Active + * 2 - Identify + * 3 - Action + */ + if (state < 0 || state > 3) + return -1; + + error = call_rtas("set-indicator", 3, 1, NULL, DR_INDICATOR, foo->slot, + state); + + if (error) + return -1; + + return 0; +} + +#DEFINE RTAS_DELAY(A) \ +if (!(A)) \ + break; \ +if ((A) == -2) { \ + if (current->need_resched) \ + schedule(); \ + continue; \ +} \ +if ((A) >= 9900) { \ + set_current_state(TASK_INTERRUPTIBLE); \ + schedule_timeout((HZ+1000)/1000); \ + continue; \ +} \ +return -1; + +int hot_add_pci(struct Foo *foo) +{ + int error; + + while(1) { + error = call_rtas("set-power-level", 2, 2, NULL, + foo->power_domain, POWER_FULL_ON); + RTAS_DELAY(error); + } + + while(1) { + error = call_rtas("set-indicator", 3, 1, NULL, ISOLATION_STATE, + foo->index, UNISOLATE); + RTAS_DELAY(error); + } + + /* configure-connector */ + + return -1; +} + +int hot_remove_pci(struct Foo *foo) +{ + int error; + + while(1) { + error = call_rtas("set-indicator", 3, 1, NULL, ISOLATION_STATE, + foo->index, ISOLATE); + RTAS_DELAY(error); + } + + while(1) { + error = call_rtas("set-power-level", 2, 2, NULL, + foo->power_domain, POWER_FULL_OFF); + RTAS_DELAY(error); + } + + return 0; +} + +void ppc_hotplug_init(void) +{ + struct device_node *p; + int *indexes, *names, *types, *power_domains; + int i; + char *name, *type; + + for (p = find_devices("pci"); p; p = p->next) { + /* + * indexes[0] is the number of indexes + * indexes[1...n] are the slot numbers + */ + indexes = (int *)get_property(p, "ibm,drc-indexes", NULL); + if (!indexes) + continue; + + /* &names[1] contains NULL terminated slot names */ + names = (int *)get_property(p, "ibm,drc-names", NULL); + if (!names) { + printk("missing ibm,drc-names\n"); + continue; + } + + /* &types[1] contains NULL terminated slot types */ + types = (int *)get_property(p, "ibm,drc-types", NULL); + if (!types) { + printk("missing ibm,drc-types\n"); + continue; + } + + /* power_domains[1...n] are the slot power domains */ + power_domains = (int *)get_property(p, + "ibm,drc-power-domains", NULL); + if (!power_domains) { + printk("missing ibm,drc-power-domains\n"); + continue; + } + + name = (char *)&names[1]; + type = (char *)&types[1]; + + for (i = 0; i < indexes[0]; i++) { + foo->slot = indexes[i]; + foo->name = name; + if (atoi(type) > 0 && atoi(type) < 11) + foo->type = atoi(type); + else + foo->type = 0; + foo->power_domain = power_domains[i]; + + name += (strlen(name) + 1); + type += (strlen(type) + 1); + } + } + + return; +}