1b6a0aa05SPeter Maydell #include "qemu/osdep.h"
23ef77acaSIgor Mammedov #include "hw/acpi/memory_hotplug.h"
33ef77acaSIgor Mammedov #include "hw/mem/pc-dimm.h"
44f70dd5fSBernhard Beschow #include "hw/boards.h"
5c06b2ffbSZhu Guihua #include "hw/qdev-core.h"
6d6454270SMarkus Armbruster #include "migration/vmstate.h"
7dfe292ffSIgor Mammedov #include "trace.h"
8e688df6bSMarkus Armbruster #include "qapi/error.h"
927c9188fSPhilippe Mathieu-Daudé #include "qapi/qapi-events-acpi.h"
10b495ec6cSPhilippe Mathieu-Daudé #include "qapi/qapi-events-machine.h"
1146f2c282SDaniel Henrique Barboza #include "qapi/qapi-events-qdev.h"
123ef77acaSIgor Mammedov
13c9c08545SIgor Mammedov #define MEMORY_SLOTS_NUMBER "MDNR"
14c9c08545SIgor Mammedov #define MEMORY_HOTPLUG_IO_REGION "HPMR"
15c9c08545SIgor Mammedov #define MEMORY_SLOT_ADDR_LOW "MRBL"
16c9c08545SIgor Mammedov #define MEMORY_SLOT_ADDR_HIGH "MRBH"
17c9c08545SIgor Mammedov #define MEMORY_SLOT_SIZE_LOW "MRLL"
18c9c08545SIgor Mammedov #define MEMORY_SLOT_SIZE_HIGH "MRLH"
19c9c08545SIgor Mammedov #define MEMORY_SLOT_PROXIMITY "MPX"
20c9c08545SIgor Mammedov #define MEMORY_SLOT_ENABLED "MES"
21c9c08545SIgor Mammedov #define MEMORY_SLOT_INSERT_EVENT "MINS"
22c9c08545SIgor Mammedov #define MEMORY_SLOT_REMOVE_EVENT "MRMV"
23c9c08545SIgor Mammedov #define MEMORY_SLOT_EJECT "MEJ"
24c9c08545SIgor Mammedov #define MEMORY_SLOT_SLECTOR "MSEL"
25c9c08545SIgor Mammedov #define MEMORY_SLOT_OST_EVENT "MOEV"
26c9c08545SIgor Mammedov #define MEMORY_SLOT_OST_STATUS "MOSC"
27c9c08545SIgor Mammedov #define MEMORY_SLOT_LOCK "MLCK"
28c9c08545SIgor Mammedov #define MEMORY_SLOT_STATUS_METHOD "MRST"
29c9c08545SIgor Mammedov #define MEMORY_SLOT_CRS_METHOD "MCRS"
30c9c08545SIgor Mammedov #define MEMORY_SLOT_OST_METHOD "MOST"
31c9c08545SIgor Mammedov #define MEMORY_SLOT_PROXIMITY_METHOD "MPXM"
32c9c08545SIgor Mammedov #define MEMORY_SLOT_EJECT_METHOD "MEJ0"
33c9c08545SIgor Mammedov #define MEMORY_SLOT_NOTIFY_METHOD "MTFY"
34c9c08545SIgor Mammedov #define MEMORY_HOTPLUG_DEVICE "MHPD"
35c9c08545SIgor Mammedov
acpi_memory_device_status(int slot,MemStatus * mdev)3643f50410SIgor Mammedov static ACPIOSTInfo *acpi_memory_device_status(int slot, MemStatus *mdev)
3743f50410SIgor Mammedov {
3843f50410SIgor Mammedov ACPIOSTInfo *info = g_new0(ACPIOSTInfo, 1);
3943f50410SIgor Mammedov
4043f50410SIgor Mammedov info->slot_type = ACPI_SLOT_TYPE_DIMM;
4143f50410SIgor Mammedov info->slot = g_strdup_printf("%d", slot);
4243f50410SIgor Mammedov info->source = mdev->ost_event;
4343f50410SIgor Mammedov info->status = mdev->ost_status;
4443f50410SIgor Mammedov if (mdev->dimm) {
4543f50410SIgor Mammedov DeviceState *dev = DEVICE(mdev->dimm);
4643f50410SIgor Mammedov if (dev->id) {
4743f50410SIgor Mammedov info->device = g_strdup(dev->id);
4843f50410SIgor Mammedov }
4943f50410SIgor Mammedov }
5043f50410SIgor Mammedov return info;
5143f50410SIgor Mammedov }
5243f50410SIgor Mammedov
acpi_memory_ospm_status(MemHotplugState * mem_st,ACPIOSTInfoList *** list)5343f50410SIgor Mammedov void acpi_memory_ospm_status(MemHotplugState *mem_st, ACPIOSTInfoList ***list)
5443f50410SIgor Mammedov {
55c3033fd3SEric Blake ACPIOSTInfoList ***tail = list;
5643f50410SIgor Mammedov int i;
5743f50410SIgor Mammedov
5843f50410SIgor Mammedov for (i = 0; i < mem_st->dev_count; i++) {
59c3033fd3SEric Blake QAPI_LIST_APPEND(*tail,
60c3033fd3SEric Blake acpi_memory_device_status(i, &mem_st->devs[i]));
6143f50410SIgor Mammedov }
6243f50410SIgor Mammedov }
6343f50410SIgor Mammedov
acpi_memory_hotplug_read(void * opaque,hwaddr addr,unsigned int size)643ef77acaSIgor Mammedov static uint64_t acpi_memory_hotplug_read(void *opaque, hwaddr addr,
653ef77acaSIgor Mammedov unsigned int size)
663ef77acaSIgor Mammedov {
673ef77acaSIgor Mammedov uint32_t val = 0;
683ef77acaSIgor Mammedov MemHotplugState *mem_st = opaque;
693ef77acaSIgor Mammedov MemStatus *mdev;
703ef77acaSIgor Mammedov Object *o;
713ef77acaSIgor Mammedov
723ef77acaSIgor Mammedov if (mem_st->selector >= mem_st->dev_count) {
73dfe292ffSIgor Mammedov trace_mhp_acpi_invalid_slot_selected(mem_st->selector);
743ef77acaSIgor Mammedov return 0;
753ef77acaSIgor Mammedov }
763ef77acaSIgor Mammedov
773ef77acaSIgor Mammedov mdev = &mem_st->devs[mem_st->selector];
783ef77acaSIgor Mammedov o = OBJECT(mdev->dimm);
793ef77acaSIgor Mammedov switch (addr) {
803ef77acaSIgor Mammedov case 0x0: /* Lo part of phys address where DIMM is mapped */
819ed442b8SMarc-André Lureau val = o ? object_property_get_uint(o, PC_DIMM_ADDR_PROP, NULL) : 0;
82dfe292ffSIgor Mammedov trace_mhp_acpi_read_addr_lo(mem_st->selector, val);
833ef77acaSIgor Mammedov break;
843ef77acaSIgor Mammedov case 0x4: /* Hi part of phys address where DIMM is mapped */
859ed442b8SMarc-André Lureau val =
869ed442b8SMarc-André Lureau o ? object_property_get_uint(o, PC_DIMM_ADDR_PROP, NULL) >> 32 : 0;
87dfe292ffSIgor Mammedov trace_mhp_acpi_read_addr_hi(mem_st->selector, val);
883ef77acaSIgor Mammedov break;
893ef77acaSIgor Mammedov case 0x8: /* Lo part of DIMM size */
90b053ef61SMarc-André Lureau val = o ? object_property_get_uint(o, PC_DIMM_SIZE_PROP, NULL) : 0;
91dfe292ffSIgor Mammedov trace_mhp_acpi_read_size_lo(mem_st->selector, val);
923ef77acaSIgor Mammedov break;
933ef77acaSIgor Mammedov case 0xc: /* Hi part of DIMM size */
94b053ef61SMarc-André Lureau val =
95b053ef61SMarc-André Lureau o ? object_property_get_uint(o, PC_DIMM_SIZE_PROP, NULL) >> 32 : 0;
96dfe292ffSIgor Mammedov trace_mhp_acpi_read_size_hi(mem_st->selector, val);
973ef77acaSIgor Mammedov break;
983ef77acaSIgor Mammedov case 0x10: /* node proximity for _PXM method */
999ed442b8SMarc-André Lureau val = o ? object_property_get_uint(o, PC_DIMM_NODE_PROP, NULL) : 0;
100dfe292ffSIgor Mammedov trace_mhp_acpi_read_pxm(mem_st->selector, val);
1013ef77acaSIgor Mammedov break;
1023ef77acaSIgor Mammedov case 0x14: /* pack and return is_* fields */
1033ef77acaSIgor Mammedov val |= mdev->is_enabled ? 1 : 0;
1043ef77acaSIgor Mammedov val |= mdev->is_inserting ? 2 : 0;
10564fec58eSTang Chen val |= mdev->is_removing ? 4 : 0;
106dfe292ffSIgor Mammedov trace_mhp_acpi_read_flags(mem_st->selector, val);
1073ef77acaSIgor Mammedov break;
1083ef77acaSIgor Mammedov default:
1093ef77acaSIgor Mammedov val = ~0;
1103ef77acaSIgor Mammedov break;
1113ef77acaSIgor Mammedov }
1123ef77acaSIgor Mammedov return val;
1133ef77acaSIgor Mammedov }
1143ef77acaSIgor Mammedov
acpi_memory_hotplug_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)1153ef77acaSIgor Mammedov static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data,
1163ef77acaSIgor Mammedov unsigned int size)
1173ef77acaSIgor Mammedov {
1183ef77acaSIgor Mammedov MemHotplugState *mem_st = opaque;
1193ef77acaSIgor Mammedov MemStatus *mdev;
1205f41fbbaSIgor Mammedov ACPIOSTInfo *info;
121c06b2ffbSZhu Guihua DeviceState *dev = NULL;
122c06b2ffbSZhu Guihua HotplugHandler *hotplug_ctrl = NULL;
123bc09e061SZhu Guihua Error *local_err = NULL;
1243ef77acaSIgor Mammedov
1253ef77acaSIgor Mammedov if (!mem_st->dev_count) {
1263ef77acaSIgor Mammedov return;
1273ef77acaSIgor Mammedov }
1283ef77acaSIgor Mammedov
1293ef77acaSIgor Mammedov if (addr) {
1303ef77acaSIgor Mammedov if (mem_st->selector >= mem_st->dev_count) {
131dfe292ffSIgor Mammedov trace_mhp_acpi_invalid_slot_selected(mem_st->selector);
1323ef77acaSIgor Mammedov return;
1333ef77acaSIgor Mammedov }
1343ef77acaSIgor Mammedov }
1353ef77acaSIgor Mammedov
1363ef77acaSIgor Mammedov switch (addr) {
1373ef77acaSIgor Mammedov case 0x0: /* DIMM slot selector */
1383ef77acaSIgor Mammedov mem_st->selector = data;
139dfe292ffSIgor Mammedov trace_mhp_acpi_write_slot(mem_st->selector);
1403ef77acaSIgor Mammedov break;
1413ef77acaSIgor Mammedov case 0x4: /* _OST event */
1423ef77acaSIgor Mammedov mdev = &mem_st->devs[mem_st->selector];
1433ef77acaSIgor Mammedov if (data == 1) {
1443ef77acaSIgor Mammedov /* TODO: handle device insert OST event */
1453ef77acaSIgor Mammedov } else if (data == 3) {
1463ef77acaSIgor Mammedov /* TODO: handle device remove OST event */
1473ef77acaSIgor Mammedov }
1483ef77acaSIgor Mammedov mdev->ost_event = data;
149dfe292ffSIgor Mammedov trace_mhp_acpi_write_ost_ev(mem_st->selector, mdev->ost_event);
1503ef77acaSIgor Mammedov break;
1513ef77acaSIgor Mammedov case 0x8: /* _OST status */
1523ef77acaSIgor Mammedov mdev = &mem_st->devs[mem_st->selector];
1533ef77acaSIgor Mammedov mdev->ost_status = data;
154dfe292ffSIgor Mammedov trace_mhp_acpi_write_ost_status(mem_st->selector, mdev->ost_status);
1553ef77acaSIgor Mammedov /* TODO: implement memory removal on guest signal */
1565f41fbbaSIgor Mammedov
1575f41fbbaSIgor Mammedov info = acpi_memory_device_status(mem_st->selector, mdev);
1583ab72385SPeter Xu qapi_event_send_acpi_device_ost(info);
1595f41fbbaSIgor Mammedov qapi_free_ACPIOSTInfo(info);
1603ef77acaSIgor Mammedov break;
161c06b2ffbSZhu Guihua case 0x14: /* set is_* fields */
1623ef77acaSIgor Mammedov mdev = &mem_st->devs[mem_st->selector];
1633ef77acaSIgor Mammedov if (data & 2) { /* clear insert event */
1643ef77acaSIgor Mammedov mdev->is_inserting = false;
165dfe292ffSIgor Mammedov trace_mhp_acpi_clear_insert_evt(mem_st->selector);
166c06b2ffbSZhu Guihua } else if (data & 4) {
167c06b2ffbSZhu Guihua mdev->is_removing = false;
168c06b2ffbSZhu Guihua trace_mhp_acpi_clear_remove_evt(mem_st->selector);
169c06b2ffbSZhu Guihua } else if (data & 8) {
170c06b2ffbSZhu Guihua if (!mdev->is_enabled) {
171c06b2ffbSZhu Guihua trace_mhp_acpi_ejecting_invalid_slot(mem_st->selector);
172c06b2ffbSZhu Guihua break;
1733ef77acaSIgor Mammedov }
174c06b2ffbSZhu Guihua
175c06b2ffbSZhu Guihua dev = DEVICE(mdev->dimm);
176c06b2ffbSZhu Guihua hotplug_ctrl = qdev_get_hotplug_handler(dev);
177c06b2ffbSZhu Guihua /* call pc-dimm unplug cb */
178bc09e061SZhu Guihua hotplug_handler_unplug(hotplug_ctrl, dev, &local_err);
179bc09e061SZhu Guihua if (local_err) {
180bc09e061SZhu Guihua trace_mhp_acpi_pc_dimm_delete_failed(mem_st->selector);
181047f2ca1SMarkus Armbruster qapi_event_send_device_unplug_guest_error(dev->id,
18246f2c282SDaniel Henrique Barboza dev->canonical_path);
183903a41d3SStefano Dong (董兴水) error_free(local_err);
184bc09e061SZhu Guihua break;
185bc09e061SZhu Guihua }
18607578b0aSDavid Hildenbrand object_unparent(OBJECT(dev));
187c06b2ffbSZhu Guihua trace_mhp_acpi_pc_dimm_deleted(mem_st->selector);
188c06b2ffbSZhu Guihua }
189c06b2ffbSZhu Guihua break;
190c06b2ffbSZhu Guihua default:
1913ef77acaSIgor Mammedov break;
1923ef77acaSIgor Mammedov }
1933ef77acaSIgor Mammedov
1943ef77acaSIgor Mammedov }
1953ef77acaSIgor Mammedov static const MemoryRegionOps acpi_memory_hotplug_ops = {
1963ef77acaSIgor Mammedov .read = acpi_memory_hotplug_read,
1973ef77acaSIgor Mammedov .write = acpi_memory_hotplug_write,
1983ef77acaSIgor Mammedov .endianness = DEVICE_LITTLE_ENDIAN,
1993ef77acaSIgor Mammedov .valid = {
2003ef77acaSIgor Mammedov .min_access_size = 1,
2013ef77acaSIgor Mammedov .max_access_size = 4,
2023ef77acaSIgor Mammedov },
2033ef77acaSIgor Mammedov };
2043ef77acaSIgor Mammedov
acpi_memory_hotplug_init(MemoryRegion * as,Object * owner,MemHotplugState * state,hwaddr io_base)2053ef77acaSIgor Mammedov void acpi_memory_hotplug_init(MemoryRegion *as, Object *owner,
206091c466eSShameer Kolothum MemHotplugState *state, hwaddr io_base)
2073ef77acaSIgor Mammedov {
2083ef77acaSIgor Mammedov MachineState *machine = MACHINE(qdev_get_machine());
2093ef77acaSIgor Mammedov
2103ef77acaSIgor Mammedov state->dev_count = machine->ram_slots;
2113ef77acaSIgor Mammedov if (!state->dev_count) {
2123ef77acaSIgor Mammedov return;
2133ef77acaSIgor Mammedov }
2143ef77acaSIgor Mammedov
2153ef77acaSIgor Mammedov state->devs = g_malloc0(sizeof(*state->devs) * state->dev_count);
2163ef77acaSIgor Mammedov memory_region_init_io(&state->io, owner, &acpi_memory_hotplug_ops, state,
21780db0e78SIgor Mammedov "acpi-mem-hotplug", MEMORY_HOTPLUG_IO_LEN);
218091c466eSShameer Kolothum memory_region_add_subregion(as, io_base, &state->io);
2193ef77acaSIgor Mammedov }
2203ef77acaSIgor Mammedov
2214aae99b6STang Chen /**
2224aae99b6STang Chen * acpi_memory_slot_status:
2234aae99b6STang Chen * @mem_st: memory hotplug state
2244aae99b6STang Chen * @dev: device
2254aae99b6STang Chen * @errp: set in case of an error
2264aae99b6STang Chen *
2274aae99b6STang Chen * Obtain a single memory slot status.
2284aae99b6STang Chen *
2294aae99b6STang Chen * This function will be called by memory unplug request cb and unplug cb.
2304aae99b6STang Chen */
2314aae99b6STang Chen static MemStatus *
acpi_memory_slot_status(MemHotplugState * mem_st,DeviceState * dev,Error ** errp)2324aae99b6STang Chen acpi_memory_slot_status(MemHotplugState *mem_st,
2333ef77acaSIgor Mammedov DeviceState *dev, Error **errp)
2343ef77acaSIgor Mammedov {
2353ef77acaSIgor Mammedov Error *local_err = NULL;
2361d515701STang Chen int slot = object_property_get_int(OBJECT(dev), PC_DIMM_SLOT_PROP,
2371d515701STang Chen &local_err);
2383ef77acaSIgor Mammedov
2393ef77acaSIgor Mammedov if (local_err) {
2403ef77acaSIgor Mammedov error_propagate(errp, local_err);
2414aae99b6STang Chen return NULL;
2423ef77acaSIgor Mammedov }
2433ef77acaSIgor Mammedov
2443ef77acaSIgor Mammedov if (slot >= mem_st->dev_count) {
2453ef77acaSIgor Mammedov char *dev_path = object_get_canonical_path(OBJECT(dev));
2464aae99b6STang Chen error_setg(errp, "acpi_memory_slot_status: "
2473ef77acaSIgor Mammedov "device [%s] returned invalid memory slot[%d]",
2483ef77acaSIgor Mammedov dev_path, slot);
2493ef77acaSIgor Mammedov g_free(dev_path);
2504aae99b6STang Chen return NULL;
2514aae99b6STang Chen }
2524aae99b6STang Chen
2534aae99b6STang Chen return &mem_st->devs[slot];
2544aae99b6STang Chen }
2554aae99b6STang Chen
acpi_memory_plug_cb(HotplugHandler * hotplug_dev,MemHotplugState * mem_st,DeviceState * dev,Error ** errp)2560058c082SIgor Mammedov void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
2574aae99b6STang Chen DeviceState *dev, Error **errp)
2584aae99b6STang Chen {
2594aae99b6STang Chen MemStatus *mdev;
26075f27498SXiao Guangrong DeviceClass *dc = DEVICE_GET_CLASS(dev);
26175f27498SXiao Guangrong
26275f27498SXiao Guangrong if (!dc->hotpluggable) {
26375f27498SXiao Guangrong return;
26475f27498SXiao Guangrong }
2654aae99b6STang Chen
2664aae99b6STang Chen mdev = acpi_memory_slot_status(mem_st, dev, errp);
2674aae99b6STang Chen if (!mdev) {
2683ef77acaSIgor Mammedov return;
2693ef77acaSIgor Mammedov }
2703ef77acaSIgor Mammedov
2713ef77acaSIgor Mammedov mdev->dimm = dev;
2723ef77acaSIgor Mammedov mdev->is_enabled = true;
2734828b10bSIgor Mammedov if (dev->hotplugged) {
2743ef77acaSIgor Mammedov mdev->is_inserting = true;
27575f27498SXiao Guangrong acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
2764828b10bSIgor Mammedov }
2773ef77acaSIgor Mammedov }
278f816a62dSIgor Mammedov
acpi_memory_unplug_request_cb(HotplugHandler * hotplug_dev,MemHotplugState * mem_st,DeviceState * dev,Error ** errp)2790058c082SIgor Mammedov void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev,
28064fec58eSTang Chen MemHotplugState *mem_st,
28164fec58eSTang Chen DeviceState *dev, Error **errp)
28264fec58eSTang Chen {
28364fec58eSTang Chen MemStatus *mdev;
28464fec58eSTang Chen
28564fec58eSTang Chen mdev = acpi_memory_slot_status(mem_st, dev, errp);
28664fec58eSTang Chen if (!mdev) {
28764fec58eSTang Chen return;
28864fec58eSTang Chen }
28964fec58eSTang Chen
29064fec58eSTang Chen mdev->is_removing = true;
2910058c082SIgor Mammedov acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
29264fec58eSTang Chen }
29364fec58eSTang Chen
acpi_memory_unplug_cb(MemHotplugState * mem_st,DeviceState * dev,Error ** errp)294f7d3e29dSTang Chen void acpi_memory_unplug_cb(MemHotplugState *mem_st,
295f7d3e29dSTang Chen DeviceState *dev, Error **errp)
296f7d3e29dSTang Chen {
297f7d3e29dSTang Chen MemStatus *mdev;
298f7d3e29dSTang Chen
299f7d3e29dSTang Chen mdev = acpi_memory_slot_status(mem_st, dev, errp);
300f7d3e29dSTang Chen if (!mdev) {
301f7d3e29dSTang Chen return;
302f7d3e29dSTang Chen }
303f7d3e29dSTang Chen
304f7d3e29dSTang Chen mdev->is_enabled = false;
305f7d3e29dSTang Chen mdev->dimm = NULL;
306f7d3e29dSTang Chen }
307f7d3e29dSTang Chen
308f816a62dSIgor Mammedov static const VMStateDescription vmstate_memhp_sts = {
309f816a62dSIgor Mammedov .name = "memory hotplug device state",
310f816a62dSIgor Mammedov .version_id = 1,
311f816a62dSIgor Mammedov .minimum_version_id = 1,
312*c559ba57SRichard Henderson .fields = (const VMStateField[]) {
313f816a62dSIgor Mammedov VMSTATE_BOOL(is_enabled, MemStatus),
314f816a62dSIgor Mammedov VMSTATE_BOOL(is_inserting, MemStatus),
315f816a62dSIgor Mammedov VMSTATE_UINT32(ost_event, MemStatus),
316f816a62dSIgor Mammedov VMSTATE_UINT32(ost_status, MemStatus),
317f816a62dSIgor Mammedov VMSTATE_END_OF_LIST()
318f816a62dSIgor Mammedov }
319f816a62dSIgor Mammedov };
320f816a62dSIgor Mammedov
321f816a62dSIgor Mammedov const VMStateDescription vmstate_memory_hotplug = {
322f816a62dSIgor Mammedov .name = "memory hotplug state",
323f816a62dSIgor Mammedov .version_id = 1,
324f816a62dSIgor Mammedov .minimum_version_id = 1,
325*c559ba57SRichard Henderson .fields = (const VMStateField[]) {
326f816a62dSIgor Mammedov VMSTATE_UINT32(selector, MemHotplugState),
327f816a62dSIgor Mammedov VMSTATE_STRUCT_VARRAY_POINTER_UINT32(devs, MemHotplugState, dev_count,
328f816a62dSIgor Mammedov vmstate_memhp_sts, MemStatus),
329f816a62dSIgor Mammedov VMSTATE_END_OF_LIST()
330f816a62dSIgor Mammedov }
331f816a62dSIgor Mammedov };
332a2088da3SIgor Mammedov
build_memory_hotplug_aml(Aml * table,uint32_t nr_mem,const char * res_root,const char * event_handler_method,AmlRegionSpace rs,hwaddr memhp_io_base)3338dfba500SIgor Mammedov void build_memory_hotplug_aml(Aml *table, uint32_t nr_mem,
334d1957dacSIgor Mammedov const char *res_root,
335091c466eSShameer Kolothum const char *event_handler_method,
336091c466eSShameer Kolothum AmlRegionSpace rs, hwaddr memhp_io_base)
337a2088da3SIgor Mammedov {
3388b35ab27SIgor Mammedov int i;
339a2088da3SIgor Mammedov Aml *ifctx;
340a2088da3SIgor Mammedov Aml *method;
341e1a58fc0SIgor Mammedov Aml *dev_container;
342a2088da3SIgor Mammedov Aml *mem_ctrl_dev;
34380db0e78SIgor Mammedov char *mhp_res_path;
344a2088da3SIgor Mammedov
34580db0e78SIgor Mammedov mhp_res_path = g_strdup_printf("%s." MEMORY_HOTPLUG_DEVICE, res_root);
346d1957dacSIgor Mammedov mem_ctrl_dev = aml_device("%s", mhp_res_path);
347a2088da3SIgor Mammedov {
3488dfba500SIgor Mammedov Aml *crs;
349a2088da3SIgor Mammedov
350a2088da3SIgor Mammedov aml_append(mem_ctrl_dev, aml_name_decl("_HID", aml_string("PNP0A06")));
351a2088da3SIgor Mammedov aml_append(mem_ctrl_dev,
352a2088da3SIgor Mammedov aml_name_decl("_UID", aml_string("Memory hotplug resources")));
353a2088da3SIgor Mammedov
3548dfba500SIgor Mammedov crs = aml_resource_template();
355091c466eSShameer Kolothum if (rs == AML_SYSTEM_IO) {
3568dfba500SIgor Mammedov aml_append(crs,
35780db0e78SIgor Mammedov aml_io(AML_DECODE16, memhp_io_base, memhp_io_base, 0,
35880db0e78SIgor Mammedov MEMORY_HOTPLUG_IO_LEN)
3598dfba500SIgor Mammedov );
360091c466eSShameer Kolothum } else {
361091c466eSShameer Kolothum aml_append(crs, aml_memory32_fixed(memhp_io_base,
362091c466eSShameer Kolothum MEMORY_HOTPLUG_IO_LEN, AML_READ_WRITE));
363091c466eSShameer Kolothum }
3648dfba500SIgor Mammedov aml_append(mem_ctrl_dev, aml_name_decl("_CRS", crs));
3658dfba500SIgor Mammedov
3668dfba500SIgor Mammedov aml_append(mem_ctrl_dev, aml_operation_region(
367091c466eSShameer Kolothum MEMORY_HOTPLUG_IO_REGION, rs,
36880db0e78SIgor Mammedov aml_int(memhp_io_base), MEMORY_HOTPLUG_IO_LEN)
3698dfba500SIgor Mammedov );
3708dfba500SIgor Mammedov
371e1a58fc0SIgor Mammedov }
372e1a58fc0SIgor Mammedov aml_append(table, mem_ctrl_dev);
373e1a58fc0SIgor Mammedov
374e1a58fc0SIgor Mammedov dev_container = aml_device(MEMORY_DEVICES_CONTAINER);
375e1a58fc0SIgor Mammedov {
376e1a58fc0SIgor Mammedov Aml *field;
377e1a58fc0SIgor Mammedov Aml *one = aml_int(1);
378e1a58fc0SIgor Mammedov Aml *zero = aml_int(0);
379e1a58fc0SIgor Mammedov Aml *ret_val = aml_local(0);
380e1a58fc0SIgor Mammedov Aml *slot_arg0 = aml_arg(0);
381e1a58fc0SIgor Mammedov Aml *slots_nr = aml_name(MEMORY_SLOTS_NUMBER);
382e1a58fc0SIgor Mammedov Aml *ctrl_lock = aml_name(MEMORY_SLOT_LOCK);
383e1a58fc0SIgor Mammedov Aml *slot_selector = aml_name(MEMORY_SLOT_SLECTOR);
384e1a58fc0SIgor Mammedov char *mmio_path = g_strdup_printf("%s." MEMORY_HOTPLUG_IO_REGION,
385e1a58fc0SIgor Mammedov mhp_res_path);
386e1a58fc0SIgor Mammedov
387e1a58fc0SIgor Mammedov aml_append(dev_container, aml_name_decl("_HID", aml_string("PNP0A06")));
388e1a58fc0SIgor Mammedov aml_append(dev_container,
389e1a58fc0SIgor Mammedov aml_name_decl("_UID", aml_string("DIMM devices")));
390e1a58fc0SIgor Mammedov
391e1a58fc0SIgor Mammedov assert(nr_mem <= ACPI_MAX_RAM_SLOTS);
392e1a58fc0SIgor Mammedov aml_append(dev_container,
393e1a58fc0SIgor Mammedov aml_name_decl(MEMORY_SLOTS_NUMBER, aml_int(nr_mem))
394e1a58fc0SIgor Mammedov );
395e1a58fc0SIgor Mammedov
396e1a58fc0SIgor Mammedov field = aml_field(mmio_path, AML_DWORD_ACC,
3978dfba500SIgor Mammedov AML_NOLOCK, AML_PRESERVE);
3988dfba500SIgor Mammedov aml_append(field, /* read only */
3998dfba500SIgor Mammedov aml_named_field(MEMORY_SLOT_ADDR_LOW, 32));
4008dfba500SIgor Mammedov aml_append(field, /* read only */
4018dfba500SIgor Mammedov aml_named_field(MEMORY_SLOT_ADDR_HIGH, 32));
4028dfba500SIgor Mammedov aml_append(field, /* read only */
4038dfba500SIgor Mammedov aml_named_field(MEMORY_SLOT_SIZE_LOW, 32));
4048dfba500SIgor Mammedov aml_append(field, /* read only */
4058dfba500SIgor Mammedov aml_named_field(MEMORY_SLOT_SIZE_HIGH, 32));
4068dfba500SIgor Mammedov aml_append(field, /* read only */
4078dfba500SIgor Mammedov aml_named_field(MEMORY_SLOT_PROXIMITY, 32));
408e1a58fc0SIgor Mammedov aml_append(dev_container, field);
4098dfba500SIgor Mammedov
410e1a58fc0SIgor Mammedov field = aml_field(mmio_path, AML_BYTE_ACC,
4118dfba500SIgor Mammedov AML_NOLOCK, AML_WRITE_AS_ZEROS);
4128dfba500SIgor Mammedov aml_append(field, aml_reserved_field(160 /* bits, Offset(20) */));
4138dfba500SIgor Mammedov aml_append(field, /* 1 if enabled, read only */
4148dfba500SIgor Mammedov aml_named_field(MEMORY_SLOT_ENABLED, 1));
4158dfba500SIgor Mammedov aml_append(field,
4168dfba500SIgor Mammedov /*(read) 1 if has a insert event. (write) 1 to clear event */
4178dfba500SIgor Mammedov aml_named_field(MEMORY_SLOT_INSERT_EVENT, 1));
4188dfba500SIgor Mammedov aml_append(field,
4198dfba500SIgor Mammedov /* (read) 1 if has a remove event. (write) 1 to clear event */
4208dfba500SIgor Mammedov aml_named_field(MEMORY_SLOT_REMOVE_EVENT, 1));
4218dfba500SIgor Mammedov aml_append(field,
4228dfba500SIgor Mammedov /* initiates device eject, write only */
4238dfba500SIgor Mammedov aml_named_field(MEMORY_SLOT_EJECT, 1));
424e1a58fc0SIgor Mammedov aml_append(dev_container, field);
4258dfba500SIgor Mammedov
426e1a58fc0SIgor Mammedov field = aml_field(mmio_path, AML_DWORD_ACC,
4278dfba500SIgor Mammedov AML_NOLOCK, AML_PRESERVE);
4288dfba500SIgor Mammedov aml_append(field, /* DIMM selector, write only */
4298dfba500SIgor Mammedov aml_named_field(MEMORY_SLOT_SLECTOR, 32));
4308dfba500SIgor Mammedov aml_append(field, /* _OST event code, write only */
4318dfba500SIgor Mammedov aml_named_field(MEMORY_SLOT_OST_EVENT, 32));
4328dfba500SIgor Mammedov aml_append(field, /* _OST status code, write only */
4338dfba500SIgor Mammedov aml_named_field(MEMORY_SLOT_OST_STATUS, 32));
434e1a58fc0SIgor Mammedov aml_append(dev_container, field);
435e1a58fc0SIgor Mammedov g_free(mmio_path);
4368dfba500SIgor Mammedov
437a2088da3SIgor Mammedov method = aml_method("_STA", 0, AML_NOTSERIALIZED);
438a2088da3SIgor Mammedov ifctx = aml_if(aml_equal(slots_nr, zero));
439a2088da3SIgor Mammedov {
440a2088da3SIgor Mammedov aml_append(ifctx, aml_return(zero));
441a2088da3SIgor Mammedov }
442a2088da3SIgor Mammedov aml_append(method, ifctx);
443a2088da3SIgor Mammedov /* present, functioning, decoding, not shown in UI */
444a2088da3SIgor Mammedov aml_append(method, aml_return(aml_int(0xB)));
445e1a58fc0SIgor Mammedov aml_append(dev_container, method);
446a2088da3SIgor Mammedov
447e1a58fc0SIgor Mammedov aml_append(dev_container, aml_mutex(MEMORY_SLOT_LOCK, 0));
448a2088da3SIgor Mammedov
449a2088da3SIgor Mammedov method = aml_method(MEMORY_SLOT_SCAN_METHOD, 0, AML_NOTSERIALIZED);
450a2088da3SIgor Mammedov {
451a2088da3SIgor Mammedov Aml *else_ctx;
452a2088da3SIgor Mammedov Aml *while_ctx;
453a2088da3SIgor Mammedov Aml *idx = aml_local(0);
454a2088da3SIgor Mammedov Aml *eject_req = aml_int(3);
455a2088da3SIgor Mammedov Aml *dev_chk = aml_int(1);
456a2088da3SIgor Mammedov
457a2088da3SIgor Mammedov ifctx = aml_if(aml_equal(slots_nr, zero));
458a2088da3SIgor Mammedov {
459a2088da3SIgor Mammedov aml_append(ifctx, aml_return(zero));
460a2088da3SIgor Mammedov }
461a2088da3SIgor Mammedov aml_append(method, ifctx);
462a2088da3SIgor Mammedov
463a2088da3SIgor Mammedov aml_append(method, aml_store(zero, idx));
464a2088da3SIgor Mammedov aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
465a2088da3SIgor Mammedov /* build AML that:
466a2088da3SIgor Mammedov * loops over all slots and Notifies DIMMs with
467a2088da3SIgor Mammedov * Device Check or Eject Request notifications if
468a2088da3SIgor Mammedov * slot has corresponding status bit set and clears
469a2088da3SIgor Mammedov * slot status.
470a2088da3SIgor Mammedov */
471a2088da3SIgor Mammedov while_ctx = aml_while(aml_lless(idx, slots_nr));
472a2088da3SIgor Mammedov {
473a2088da3SIgor Mammedov Aml *ins_evt = aml_name(MEMORY_SLOT_INSERT_EVENT);
474a2088da3SIgor Mammedov Aml *rm_evt = aml_name(MEMORY_SLOT_REMOVE_EVENT);
475a2088da3SIgor Mammedov
476a2088da3SIgor Mammedov aml_append(while_ctx, aml_store(idx, slot_selector));
477a2088da3SIgor Mammedov ifctx = aml_if(aml_equal(ins_evt, one));
478a2088da3SIgor Mammedov {
479a2088da3SIgor Mammedov aml_append(ifctx,
480a2088da3SIgor Mammedov aml_call2(MEMORY_SLOT_NOTIFY_METHOD,
481a2088da3SIgor Mammedov idx, dev_chk));
482a2088da3SIgor Mammedov aml_append(ifctx, aml_store(one, ins_evt));
483a2088da3SIgor Mammedov }
484a2088da3SIgor Mammedov aml_append(while_ctx, ifctx);
485a2088da3SIgor Mammedov
486a2088da3SIgor Mammedov else_ctx = aml_else();
487a2088da3SIgor Mammedov ifctx = aml_if(aml_equal(rm_evt, one));
488a2088da3SIgor Mammedov {
489a2088da3SIgor Mammedov aml_append(ifctx,
490a2088da3SIgor Mammedov aml_call2(MEMORY_SLOT_NOTIFY_METHOD,
491a2088da3SIgor Mammedov idx, eject_req));
492a2088da3SIgor Mammedov aml_append(ifctx, aml_store(one, rm_evt));
493a2088da3SIgor Mammedov }
494a2088da3SIgor Mammedov aml_append(else_ctx, ifctx);
495a2088da3SIgor Mammedov aml_append(while_ctx, else_ctx);
496a2088da3SIgor Mammedov
497a2088da3SIgor Mammedov aml_append(while_ctx, aml_add(idx, one, idx));
498a2088da3SIgor Mammedov }
499a2088da3SIgor Mammedov aml_append(method, while_ctx);
500a2088da3SIgor Mammedov aml_append(method, aml_release(ctrl_lock));
501a2088da3SIgor Mammedov aml_append(method, aml_return(one));
502a2088da3SIgor Mammedov }
503e1a58fc0SIgor Mammedov aml_append(dev_container, method);
504a2088da3SIgor Mammedov
505a2088da3SIgor Mammedov method = aml_method(MEMORY_SLOT_STATUS_METHOD, 1, AML_NOTSERIALIZED);
506a2088da3SIgor Mammedov {
507a2088da3SIgor Mammedov Aml *slot_enabled = aml_name(MEMORY_SLOT_ENABLED);
508a2088da3SIgor Mammedov
509a2088da3SIgor Mammedov aml_append(method, aml_store(zero, ret_val));
510a2088da3SIgor Mammedov aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
511a2088da3SIgor Mammedov aml_append(method,
512a2088da3SIgor Mammedov aml_store(aml_to_integer(slot_arg0), slot_selector));
513a2088da3SIgor Mammedov
514a2088da3SIgor Mammedov ifctx = aml_if(aml_equal(slot_enabled, one));
515a2088da3SIgor Mammedov {
516a2088da3SIgor Mammedov aml_append(ifctx, aml_store(aml_int(0xF), ret_val));
517a2088da3SIgor Mammedov }
518a2088da3SIgor Mammedov aml_append(method, ifctx);
519a2088da3SIgor Mammedov
520a2088da3SIgor Mammedov aml_append(method, aml_release(ctrl_lock));
521a2088da3SIgor Mammedov aml_append(method, aml_return(ret_val));
522a2088da3SIgor Mammedov }
523e1a58fc0SIgor Mammedov aml_append(dev_container, method);
524a2088da3SIgor Mammedov
525a2088da3SIgor Mammedov method = aml_method(MEMORY_SLOT_CRS_METHOD, 1, AML_SERIALIZED);
526a2088da3SIgor Mammedov {
527a2088da3SIgor Mammedov Aml *mr64 = aml_name("MR64");
528a2088da3SIgor Mammedov Aml *mr32 = aml_name("MR32");
529a2088da3SIgor Mammedov Aml *crs_tmpl = aml_resource_template();
530a2088da3SIgor Mammedov Aml *minl = aml_name("MINL");
531a2088da3SIgor Mammedov Aml *minh = aml_name("MINH");
532a2088da3SIgor Mammedov Aml *maxl = aml_name("MAXL");
533a2088da3SIgor Mammedov Aml *maxh = aml_name("MAXH");
534a2088da3SIgor Mammedov Aml *lenl = aml_name("LENL");
535a2088da3SIgor Mammedov Aml *lenh = aml_name("LENH");
536a2088da3SIgor Mammedov
537a2088da3SIgor Mammedov aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
538a2088da3SIgor Mammedov aml_append(method, aml_store(aml_to_integer(slot_arg0),
539a2088da3SIgor Mammedov slot_selector));
540a2088da3SIgor Mammedov
541a2088da3SIgor Mammedov aml_append(crs_tmpl,
542a2088da3SIgor Mammedov aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
543a2088da3SIgor Mammedov AML_CACHEABLE, AML_READ_WRITE,
544a2088da3SIgor Mammedov 0, 0x0, 0xFFFFFFFFFFFFFFFEULL, 0,
545a2088da3SIgor Mammedov 0xFFFFFFFFFFFFFFFFULL));
546a2088da3SIgor Mammedov aml_append(method, aml_name_decl("MR64", crs_tmpl));
547a2088da3SIgor Mammedov aml_append(method,
548a2088da3SIgor Mammedov aml_create_dword_field(mr64, aml_int(14), "MINL"));
549a2088da3SIgor Mammedov aml_append(method,
550a2088da3SIgor Mammedov aml_create_dword_field(mr64, aml_int(18), "MINH"));
551a2088da3SIgor Mammedov aml_append(method,
552a2088da3SIgor Mammedov aml_create_dword_field(mr64, aml_int(38), "LENL"));
553a2088da3SIgor Mammedov aml_append(method,
554a2088da3SIgor Mammedov aml_create_dword_field(mr64, aml_int(42), "LENH"));
555a2088da3SIgor Mammedov aml_append(method,
556a2088da3SIgor Mammedov aml_create_dword_field(mr64, aml_int(22), "MAXL"));
557a2088da3SIgor Mammedov aml_append(method,
558a2088da3SIgor Mammedov aml_create_dword_field(mr64, aml_int(26), "MAXH"));
559a2088da3SIgor Mammedov
560a2088da3SIgor Mammedov aml_append(method,
561a2088da3SIgor Mammedov aml_store(aml_name(MEMORY_SLOT_ADDR_HIGH), minh));
562a2088da3SIgor Mammedov aml_append(method,
563a2088da3SIgor Mammedov aml_store(aml_name(MEMORY_SLOT_ADDR_LOW), minl));
564a2088da3SIgor Mammedov aml_append(method,
565a2088da3SIgor Mammedov aml_store(aml_name(MEMORY_SLOT_SIZE_HIGH), lenh));
566a2088da3SIgor Mammedov aml_append(method,
567a2088da3SIgor Mammedov aml_store(aml_name(MEMORY_SLOT_SIZE_LOW), lenl));
568a2088da3SIgor Mammedov
569a2088da3SIgor Mammedov /* 64-bit math: MAX = MIN + LEN - 1 */
570a2088da3SIgor Mammedov aml_append(method, aml_add(minl, lenl, maxl));
571a2088da3SIgor Mammedov aml_append(method, aml_add(minh, lenh, maxh));
572a2088da3SIgor Mammedov ifctx = aml_if(aml_lless(maxl, minl));
573a2088da3SIgor Mammedov {
574a2088da3SIgor Mammedov aml_append(ifctx, aml_add(maxh, one, maxh));
575a2088da3SIgor Mammedov }
576a2088da3SIgor Mammedov aml_append(method, ifctx);
577a2088da3SIgor Mammedov ifctx = aml_if(aml_lless(maxl, one));
578a2088da3SIgor Mammedov {
579a2088da3SIgor Mammedov aml_append(ifctx, aml_subtract(maxh, one, maxh));
580a2088da3SIgor Mammedov }
581a2088da3SIgor Mammedov aml_append(method, ifctx);
582a2088da3SIgor Mammedov aml_append(method, aml_subtract(maxl, one, maxl));
583a2088da3SIgor Mammedov
584a2088da3SIgor Mammedov /* return 32-bit _CRS if addr/size is in low mem */
585a2088da3SIgor Mammedov /* TODO: remove it since all hotplugged DIMMs are in high mem */
586a2088da3SIgor Mammedov ifctx = aml_if(aml_equal(maxh, zero));
587a2088da3SIgor Mammedov {
588a2088da3SIgor Mammedov crs_tmpl = aml_resource_template();
589a2088da3SIgor Mammedov aml_append(crs_tmpl,
590a2088da3SIgor Mammedov aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED,
591a2088da3SIgor Mammedov AML_MAX_FIXED, AML_CACHEABLE,
592a2088da3SIgor Mammedov AML_READ_WRITE,
593a2088da3SIgor Mammedov 0, 0x0, 0xFFFFFFFE, 0,
594a2088da3SIgor Mammedov 0xFFFFFFFF));
595a2088da3SIgor Mammedov aml_append(ifctx, aml_name_decl("MR32", crs_tmpl));
596a2088da3SIgor Mammedov aml_append(ifctx,
597a2088da3SIgor Mammedov aml_create_dword_field(mr32, aml_int(10), "MIN"));
598a2088da3SIgor Mammedov aml_append(ifctx,
599a2088da3SIgor Mammedov aml_create_dword_field(mr32, aml_int(14), "MAX"));
600a2088da3SIgor Mammedov aml_append(ifctx,
601a2088da3SIgor Mammedov aml_create_dword_field(mr32, aml_int(22), "LEN"));
602a2088da3SIgor Mammedov aml_append(ifctx, aml_store(minl, aml_name("MIN")));
603a2088da3SIgor Mammedov aml_append(ifctx, aml_store(maxl, aml_name("MAX")));
604a2088da3SIgor Mammedov aml_append(ifctx, aml_store(lenl, aml_name("LEN")));
605a2088da3SIgor Mammedov
606a2088da3SIgor Mammedov aml_append(ifctx, aml_release(ctrl_lock));
607a2088da3SIgor Mammedov aml_append(ifctx, aml_return(mr32));
608a2088da3SIgor Mammedov }
609a2088da3SIgor Mammedov aml_append(method, ifctx);
610a2088da3SIgor Mammedov
611a2088da3SIgor Mammedov aml_append(method, aml_release(ctrl_lock));
612a2088da3SIgor Mammedov aml_append(method, aml_return(mr64));
613a2088da3SIgor Mammedov }
614e1a58fc0SIgor Mammedov aml_append(dev_container, method);
615a2088da3SIgor Mammedov
616a2088da3SIgor Mammedov method = aml_method(MEMORY_SLOT_PROXIMITY_METHOD, 1,
617a2088da3SIgor Mammedov AML_NOTSERIALIZED);
618a2088da3SIgor Mammedov {
619a2088da3SIgor Mammedov Aml *proximity = aml_name(MEMORY_SLOT_PROXIMITY);
620a2088da3SIgor Mammedov
621a2088da3SIgor Mammedov aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
622a2088da3SIgor Mammedov aml_append(method, aml_store(aml_to_integer(slot_arg0),
623a2088da3SIgor Mammedov slot_selector));
624a2088da3SIgor Mammedov aml_append(method, aml_store(proximity, ret_val));
625a2088da3SIgor Mammedov aml_append(method, aml_release(ctrl_lock));
626a2088da3SIgor Mammedov aml_append(method, aml_return(ret_val));
627a2088da3SIgor Mammedov }
628e1a58fc0SIgor Mammedov aml_append(dev_container, method);
629a2088da3SIgor Mammedov
630a2088da3SIgor Mammedov method = aml_method(MEMORY_SLOT_OST_METHOD, 4, AML_NOTSERIALIZED);
631a2088da3SIgor Mammedov {
632a2088da3SIgor Mammedov Aml *ost_evt = aml_name(MEMORY_SLOT_OST_EVENT);
633a2088da3SIgor Mammedov Aml *ost_status = aml_name(MEMORY_SLOT_OST_STATUS);
634a2088da3SIgor Mammedov
635a2088da3SIgor Mammedov aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
636a2088da3SIgor Mammedov aml_append(method, aml_store(aml_to_integer(slot_arg0),
637a2088da3SIgor Mammedov slot_selector));
638a2088da3SIgor Mammedov aml_append(method, aml_store(aml_arg(1), ost_evt));
639a2088da3SIgor Mammedov aml_append(method, aml_store(aml_arg(2), ost_status));
640a2088da3SIgor Mammedov aml_append(method, aml_release(ctrl_lock));
641a2088da3SIgor Mammedov }
642e1a58fc0SIgor Mammedov aml_append(dev_container, method);
643a2088da3SIgor Mammedov
644a2088da3SIgor Mammedov method = aml_method(MEMORY_SLOT_EJECT_METHOD, 2, AML_NOTSERIALIZED);
645a2088da3SIgor Mammedov {
646a2088da3SIgor Mammedov Aml *eject = aml_name(MEMORY_SLOT_EJECT);
647a2088da3SIgor Mammedov
648a2088da3SIgor Mammedov aml_append(method, aml_acquire(ctrl_lock, 0xFFFF));
649a2088da3SIgor Mammedov aml_append(method, aml_store(aml_to_integer(slot_arg0),
650a2088da3SIgor Mammedov slot_selector));
651a2088da3SIgor Mammedov aml_append(method, aml_store(one, eject));
652a2088da3SIgor Mammedov aml_append(method, aml_release(ctrl_lock));
653a2088da3SIgor Mammedov }
654e1a58fc0SIgor Mammedov aml_append(dev_container, method);
65575ff0f0cSIgor Mammedov
65675ff0f0cSIgor Mammedov /* build memory devices */
65775ff0f0cSIgor Mammedov for (i = 0; i < nr_mem; i++) {
6588b35ab27SIgor Mammedov Aml *dev;
659e1a58fc0SIgor Mammedov const char *s;
66075ff0f0cSIgor Mammedov
66175ff0f0cSIgor Mammedov dev = aml_device("MP%02X", i);
66275ff0f0cSIgor Mammedov aml_append(dev, aml_name_decl("_UID", aml_string("0x%02X", i)));
66375ff0f0cSIgor Mammedov aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C80")));
66475ff0f0cSIgor Mammedov
66575ff0f0cSIgor Mammedov method = aml_method("_CRS", 0, AML_NOTSERIALIZED);
666e1a58fc0SIgor Mammedov s = MEMORY_SLOT_CRS_METHOD;
66775ff0f0cSIgor Mammedov aml_append(method, aml_return(aml_call1(s, aml_name("_UID"))));
66875ff0f0cSIgor Mammedov aml_append(dev, method);
66975ff0f0cSIgor Mammedov
67075ff0f0cSIgor Mammedov method = aml_method("_STA", 0, AML_NOTSERIALIZED);
671e1a58fc0SIgor Mammedov s = MEMORY_SLOT_STATUS_METHOD;
67275ff0f0cSIgor Mammedov aml_append(method, aml_return(aml_call1(s, aml_name("_UID"))));
67375ff0f0cSIgor Mammedov aml_append(dev, method);
67475ff0f0cSIgor Mammedov
67575ff0f0cSIgor Mammedov method = aml_method("_PXM", 0, AML_NOTSERIALIZED);
676e1a58fc0SIgor Mammedov s = MEMORY_SLOT_PROXIMITY_METHOD;
67775ff0f0cSIgor Mammedov aml_append(method, aml_return(aml_call1(s, aml_name("_UID"))));
67875ff0f0cSIgor Mammedov aml_append(dev, method);
67975ff0f0cSIgor Mammedov
68075ff0f0cSIgor Mammedov method = aml_method("_OST", 3, AML_NOTSERIALIZED);
681e1a58fc0SIgor Mammedov s = MEMORY_SLOT_OST_METHOD;
682e674132aSYang Zhong aml_append(method,
683e674132aSYang Zhong aml_call4(s, aml_name("_UID"), aml_arg(0),
684e674132aSYang Zhong aml_arg(1), aml_arg(2)));
68575ff0f0cSIgor Mammedov aml_append(dev, method);
68675ff0f0cSIgor Mammedov
68775ff0f0cSIgor Mammedov method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
688e1a58fc0SIgor Mammedov s = MEMORY_SLOT_EJECT_METHOD;
689e674132aSYang Zhong aml_append(method,
690e674132aSYang Zhong aml_call2(s, aml_name("_UID"), aml_arg(0)));
69175ff0f0cSIgor Mammedov aml_append(dev, method);
69275ff0f0cSIgor Mammedov
693e1a58fc0SIgor Mammedov aml_append(dev_container, dev);
69475ff0f0cSIgor Mammedov }
69575ff0f0cSIgor Mammedov
69675ff0f0cSIgor Mammedov /* build Method(MEMORY_SLOT_NOTIFY_METHOD, 2) {
69775ff0f0cSIgor Mammedov * If (LEqual(Arg0, 0x00)) {Notify(MP00, Arg1)} ... }
69875ff0f0cSIgor Mammedov */
69975ff0f0cSIgor Mammedov method = aml_method(MEMORY_SLOT_NOTIFY_METHOD, 2, AML_NOTSERIALIZED);
70075ff0f0cSIgor Mammedov for (i = 0; i < nr_mem; i++) {
70175ff0f0cSIgor Mammedov ifctx = aml_if(aml_equal(aml_arg(0), aml_int(i)));
70275ff0f0cSIgor Mammedov aml_append(ifctx,
70375ff0f0cSIgor Mammedov aml_notify(aml_name("MP%.02X", i), aml_arg(1))
70475ff0f0cSIgor Mammedov );
70575ff0f0cSIgor Mammedov aml_append(method, ifctx);
70675ff0f0cSIgor Mammedov }
707e1a58fc0SIgor Mammedov aml_append(dev_container, method);
708e1a58fc0SIgor Mammedov }
709e1a58fc0SIgor Mammedov aml_append(table, dev_container);
710d1957dacSIgor Mammedov
71122338feaSSamuel Ortiz if (event_handler_method) {
712d1957dacSIgor Mammedov method = aml_method(event_handler_method, 0, AML_NOTSERIALIZED);
71322338feaSSamuel Ortiz aml_append(method, aml_call0(MEMORY_DEVICES_CONTAINER "."
71422338feaSSamuel Ortiz MEMORY_SLOT_SCAN_METHOD));
715d1957dacSIgor Mammedov aml_append(table, method);
71622338feaSSamuel Ortiz }
717d1957dacSIgor Mammedov
718d1957dacSIgor Mammedov g_free(mhp_res_path);
71975ff0f0cSIgor Mammedov }
720