1*84053e14Sjsg /* $OpenBSD: acpipci.c,v 1.9 2024/10/10 05:51:23 jsg Exp $ */ 203a88dc8Skettenis /* 303a88dc8Skettenis * Copyright (c) 2018 Mark Kettenis 403a88dc8Skettenis * 503a88dc8Skettenis * Permission to use, copy, modify, and distribute this software for any 603a88dc8Skettenis * purpose with or without fee is hereby granted, provided that the above 703a88dc8Skettenis * copyright notice and this permission notice appear in all copies. 803a88dc8Skettenis * 903a88dc8Skettenis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1003a88dc8Skettenis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1103a88dc8Skettenis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1203a88dc8Skettenis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1303a88dc8Skettenis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1403a88dc8Skettenis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1503a88dc8Skettenis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1603a88dc8Skettenis */ 1703a88dc8Skettenis 1803a88dc8Skettenis #include <sys/param.h> 1903a88dc8Skettenis #include <sys/device.h> 2003a88dc8Skettenis #include <sys/extent.h> 2103a88dc8Skettenis #include <sys/malloc.h> 2203a88dc8Skettenis #include <sys/systm.h> 2303a88dc8Skettenis 2403a88dc8Skettenis #include <dev/acpi/acpireg.h> 2503a88dc8Skettenis #include <dev/acpi/acpivar.h> 2603a88dc8Skettenis #include <dev/acpi/acpidev.h> 2703a88dc8Skettenis #include <dev/acpi/amltypes.h> 2803a88dc8Skettenis #include <dev/acpi/dsdt.h> 2903a88dc8Skettenis 3003a88dc8Skettenis #include <dev/pci/pcidevs.h> 3103a88dc8Skettenis #include <dev/pci/pcireg.h> 3203a88dc8Skettenis #include <dev/pci/pcivar.h> 3303a88dc8Skettenis 3403a88dc8Skettenis /* 33DB4D5B-1FF7-401C-9657-7441C03DD766 */ 3503a88dc8Skettenis #define ACPI_PCI_UUID \ 3603a88dc8Skettenis { 0x5b, 0x4d, 0xdb, 0x33, \ 3703a88dc8Skettenis 0xf7, 0x1f, \ 3803a88dc8Skettenis 0x1c, 0x40, \ 3903a88dc8Skettenis 0x96, 0x57, \ 4003a88dc8Skettenis 0x74, 0x41, 0xc0, 0x3d, 0xd7, 0x66 } 4103a88dc8Skettenis 4203a88dc8Skettenis /* Support field. */ 4303a88dc8Skettenis #define ACPI_PCI_PCIE_CONFIG 0x00000001 4403a88dc8Skettenis #define ACPI_PCI_ASPM 0x00000002 4503a88dc8Skettenis #define ACPI_PCI_CPMC 0x00000004 4603a88dc8Skettenis #define ACPI_PCI_SEGMENTS 0x00000008 4703a88dc8Skettenis #define ACPI_PCI_MSI 0x00000010 4803a88dc8Skettenis 4903a88dc8Skettenis /* Control field. */ 5003a88dc8Skettenis #define ACPI_PCI_PCIE_HOTPLUG 0x00000001 5103a88dc8Skettenis 5203a88dc8Skettenis struct acpipci_softc { 5303a88dc8Skettenis struct device sc_dev; 5403a88dc8Skettenis struct acpi_softc *sc_acpi; 5503a88dc8Skettenis struct aml_node *sc_node; 56a6e4dcfbSkettenis 57a6e4dcfbSkettenis bus_space_tag_t sc_iot; 58a6e4dcfbSkettenis bus_space_tag_t sc_memt; 59a6e4dcfbSkettenis bus_dma_tag_t sc_dmat; 60a6e4dcfbSkettenis 61a6e4dcfbSkettenis struct extent *sc_busex; 62a6e4dcfbSkettenis struct extent *sc_memex; 63a6e4dcfbSkettenis struct extent *sc_ioex; 64a6e4dcfbSkettenis char sc_busex_name[32]; 65a6e4dcfbSkettenis char sc_ioex_name[32]; 66a6e4dcfbSkettenis char sc_memex_name[32]; 67a6e4dcfbSkettenis int sc_bus; 68a6e4dcfbSkettenis uint32_t sc_seg; 6903a88dc8Skettenis }; 7003a88dc8Skettenis 7103a88dc8Skettenis int acpipci_match(struct device *, void *, void *); 7203a88dc8Skettenis void acpipci_attach(struct device *, struct device *, void *); 7303a88dc8Skettenis 7406a6f48eSmpi const struct cfattach acpipci_ca = { 7503a88dc8Skettenis sizeof(struct acpipci_softc), acpipci_match, acpipci_attach 7603a88dc8Skettenis }; 7703a88dc8Skettenis 7803a88dc8Skettenis struct cfdriver acpipci_cd = { 7903a88dc8Skettenis NULL, "acpipci", DV_DULL 8003a88dc8Skettenis }; 8103a88dc8Skettenis 8203a88dc8Skettenis const char *acpipci_hids[] = { 8303a88dc8Skettenis "PNP0A08", 8403a88dc8Skettenis "PNP0A03", 8503a88dc8Skettenis NULL 8603a88dc8Skettenis }; 8703a88dc8Skettenis 88a6e4dcfbSkettenis int acpipci_print(void *, const char *); 89a6e4dcfbSkettenis int acpipci_parse_resources(int, union acpi_resource *, void *); 90a6e4dcfbSkettenis void acpipci_osc(struct acpipci_softc *); 91a6e4dcfbSkettenis 9203a88dc8Skettenis int 9303a88dc8Skettenis acpipci_match(struct device *parent, void *match, void *aux) 9403a88dc8Skettenis { 9503a88dc8Skettenis struct acpi_attach_args *aaa = aux; 9603a88dc8Skettenis struct cfdata *cf = match; 9703a88dc8Skettenis 9803a88dc8Skettenis return acpi_matchhids(aaa, acpipci_hids, cf->cf_driver->cd_name); 9903a88dc8Skettenis } 10003a88dc8Skettenis 10103a88dc8Skettenis void 10203a88dc8Skettenis acpipci_attach(struct device *parent, struct device *self, void *aux) 10303a88dc8Skettenis { 10403a88dc8Skettenis struct acpi_attach_args *aaa = aux; 10503a88dc8Skettenis struct acpipci_softc *sc = (struct acpipci_softc *)self; 1069a33df95Skettenis struct aml_value res; 107a6e4dcfbSkettenis uint64_t bbn = 0; 108a6e4dcfbSkettenis uint64_t seg = 0; 109a6e4dcfbSkettenis 110a6e4dcfbSkettenis acpi_haspci = 1; 111a6e4dcfbSkettenis 112a6e4dcfbSkettenis sc->sc_iot = aaa->aaa_iot; 113a6e4dcfbSkettenis sc->sc_memt = aaa->aaa_memt; 114a6e4dcfbSkettenis sc->sc_dmat = aaa->aaa_dmat; 1159a33df95Skettenis 11638f3385cSkettenis sc->sc_acpi = (struct acpi_softc *)parent; 11738f3385cSkettenis sc->sc_node = aaa->aaa_node; 11838f3385cSkettenis printf(" %s", sc->sc_node->name); 11938f3385cSkettenis 120a6e4dcfbSkettenis acpipci_osc(sc); 121a6e4dcfbSkettenis 122a6e4dcfbSkettenis aml_evalinteger(sc->sc_acpi, sc->sc_node, "_BBN", 0, NULL, &bbn); 123a6e4dcfbSkettenis sc->sc_bus = bbn; 124a6e4dcfbSkettenis 125a6e4dcfbSkettenis aml_evalinteger(sc->sc_acpi, sc->sc_node, "_SEG", 0, NULL, &seg); 126a6e4dcfbSkettenis sc->sc_seg = seg; 127a6e4dcfbSkettenis 128a6e4dcfbSkettenis if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) { 129a6e4dcfbSkettenis printf(": can't find resources\n"); 130a6e4dcfbSkettenis 131a6e4dcfbSkettenis pci_init_extents(); 132a6e4dcfbSkettenis sc->sc_busex = pcibus_ex; 133a6e4dcfbSkettenis sc->sc_ioex = pciio_ex; 134a6e4dcfbSkettenis sc->sc_memex = pcimem_ex; 135a6e4dcfbSkettenis 136a6e4dcfbSkettenis return; 137a6e4dcfbSkettenis } 138a6e4dcfbSkettenis 139a6e4dcfbSkettenis /* Create extents for our address spaces. */ 140a6e4dcfbSkettenis snprintf(sc->sc_busex_name, sizeof(sc->sc_busex_name), 141a6e4dcfbSkettenis "%s pcibus", sc->sc_dev.dv_xname); 142a6e4dcfbSkettenis snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name), 143a6e4dcfbSkettenis "%s pciio", sc->sc_dev.dv_xname); 144a6e4dcfbSkettenis snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name), 145a6e4dcfbSkettenis "%s pcimem", sc->sc_dev.dv_xname); 146a6e4dcfbSkettenis sc->sc_busex = extent_create(sc->sc_busex_name, 0, 255, 147a6e4dcfbSkettenis M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 148a6e4dcfbSkettenis sc->sc_ioex = extent_create(sc->sc_ioex_name, 0, 0xffffffff, 149a6e4dcfbSkettenis M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 150a6e4dcfbSkettenis sc->sc_memex = extent_create(sc->sc_memex_name, 0, (u_long)-1, 151a6e4dcfbSkettenis M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 152a6e4dcfbSkettenis 153a6e4dcfbSkettenis aml_parse_resource(&res, acpipci_parse_resources, sc); 154a6e4dcfbSkettenis 155a6e4dcfbSkettenis if (sc->sc_acpi->sc_major < 5) { 156a6e4dcfbSkettenis extent_destroy(sc->sc_ioex); 157a6e4dcfbSkettenis extent_destroy(sc->sc_memex); 158a6e4dcfbSkettenis 159a6e4dcfbSkettenis pci_init_extents(); 160a6e4dcfbSkettenis sc->sc_ioex = pciio_ex; 161a6e4dcfbSkettenis sc->sc_memex = pcimem_ex; 162a6e4dcfbSkettenis } 163a6e4dcfbSkettenis 164a6e4dcfbSkettenis printf("\n"); 165a6e4dcfbSkettenis 16623834b0fSkettenis #ifdef ACPIPCI_DEBUG 167a6e4dcfbSkettenis extent_print(sc->sc_busex); 168a6e4dcfbSkettenis extent_print(sc->sc_ioex); 169a6e4dcfbSkettenis extent_print(sc->sc_memex); 170a6e4dcfbSkettenis #endif 171a6e4dcfbSkettenis } 172a6e4dcfbSkettenis 173a6e4dcfbSkettenis void 174a6e4dcfbSkettenis acpipci_attach_bus(struct device *parent, struct acpipci_softc *sc) 175a6e4dcfbSkettenis { 176a6e4dcfbSkettenis struct pcibus_attach_args pba; 177a6e4dcfbSkettenis pcitag_t tag; 178a6e4dcfbSkettenis pcireg_t id, class; 179a6e4dcfbSkettenis 180a6e4dcfbSkettenis memset(&pba, 0, sizeof(pba)); 181a6e4dcfbSkettenis pba.pba_busname = "pci"; 182a6e4dcfbSkettenis pba.pba_iot = sc->sc_iot; 183a6e4dcfbSkettenis pba.pba_memt = sc->sc_memt; 184a6e4dcfbSkettenis pba.pba_dmat = sc->sc_dmat; 185a6e4dcfbSkettenis pba.pba_busex = sc->sc_busex; 186a6e4dcfbSkettenis pba.pba_ioex = sc->sc_ioex; 187a6e4dcfbSkettenis pba.pba_memex = sc->sc_memex; 188a6e4dcfbSkettenis pba.pba_pmemex = sc->sc_memex; 189a6e4dcfbSkettenis pba.pba_domain = pci_ndomains++; 190a6e4dcfbSkettenis pba.pba_bus = sc->sc_bus; 191a6e4dcfbSkettenis 192a6e4dcfbSkettenis /* Enable MSI in ACPI 2.0 and above, unless we're told not to. */ 193a6e4dcfbSkettenis if (sc->sc_acpi->sc_fadt->hdr.revision >= 2 && 194a6e4dcfbSkettenis (sc->sc_acpi->sc_fadt->iapc_boot_arch & FADT_NO_MSI) == 0) 195a6e4dcfbSkettenis pba.pba_flags |= PCI_FLAGS_MSI_ENABLED; 196a6e4dcfbSkettenis 197*84053e14Sjsg /* Enable MSI for QEMU claiming ACPI 1.0 */ 198*84053e14Sjsg tag = pci_make_tag(pba.pba_pc, sc->sc_bus, 0, 0); 199*84053e14Sjsg id = pci_conf_read(pba.pba_pc, tag, PCI_SUBSYS_ID_REG); 200*84053e14Sjsg if (sc->sc_acpi->sc_fadt->hdr.revision == 1 && 201*84053e14Sjsg PCI_VENDOR(id) == PCI_VENDOR_QUMRANET) 202*84053e14Sjsg pba.pba_flags |= PCI_FLAGS_MSI_ENABLED; 203*84053e14Sjsg 204a6e4dcfbSkettenis /* 20536fd90dcSjsg * Don't enable MSI on chipsets from low-end manufacturers 206a6e4dcfbSkettenis * like VIA and SiS. We do this by looking at the host 207a6e4dcfbSkettenis * bridge, which should be device 0 function 0. 208a6e4dcfbSkettenis */ 209a6e4dcfbSkettenis id = pci_conf_read(pba.pba_pc, tag, PCI_ID_REG); 210a6e4dcfbSkettenis class = pci_conf_read(pba.pba_pc, tag, PCI_CLASS_REG); 211a6e4dcfbSkettenis if (PCI_CLASS(class) == PCI_CLASS_BRIDGE && 212a6e4dcfbSkettenis PCI_SUBCLASS(class) != PCI_SUBCLASS_BRIDGE_HOST && 213a6e4dcfbSkettenis PCI_VENDOR(id) != PCI_VENDOR_AMD && 214a6e4dcfbSkettenis PCI_VENDOR(id) != PCI_VENDOR_NVIDIA && 215a6e4dcfbSkettenis PCI_VENDOR(id) != PCI_VENDOR_INTEL) 216a6e4dcfbSkettenis pba.pba_flags &= ~PCI_FLAGS_MSI_ENABLED; 217a6e4dcfbSkettenis 218a6e4dcfbSkettenis /* 219a6e4dcfbSkettenis * Don't enable MSI on a HyperTransport bus. In order to 220a6e4dcfbSkettenis * determine that a bus is a HyperTransport bus, we look at 221a6e4dcfbSkettenis * device 24 function 0, which is the HyperTransport 222a6e4dcfbSkettenis * host/primary interface integrated on most 64-bit AMD CPUs. 223a6e4dcfbSkettenis * If that device has a HyperTransport capability, this must 224a6e4dcfbSkettenis * be a HyperTransport bus and we disable MSI. 225a6e4dcfbSkettenis */ 226a6e4dcfbSkettenis tag = pci_make_tag(pba.pba_pc, sc->sc_bus, 24, 0); 227a6e4dcfbSkettenis if (pci_get_capability(pba.pba_pc, tag, PCI_CAP_HT, NULL, NULL)) 228a6e4dcfbSkettenis pba.pba_flags &= ~PCI_FLAGS_MSI_ENABLED; 229a6e4dcfbSkettenis 230a6e4dcfbSkettenis config_found(parent, &pba, acpipci_print); 231a6e4dcfbSkettenis } 232a6e4dcfbSkettenis 233a6e4dcfbSkettenis void 234a6e4dcfbSkettenis acpipci_attach_busses(struct device *parent) 235a6e4dcfbSkettenis { 236a6e4dcfbSkettenis int i; 237a6e4dcfbSkettenis 238a6e4dcfbSkettenis for (i = 0; i < acpipci_cd.cd_ndevs; i++) { 239a6e4dcfbSkettenis if (acpipci_cd.cd_devs[i]) 240a6e4dcfbSkettenis acpipci_attach_bus(parent, acpipci_cd.cd_devs[i]); 241a6e4dcfbSkettenis } 242a6e4dcfbSkettenis } 243a6e4dcfbSkettenis 244a6e4dcfbSkettenis int 245a6e4dcfbSkettenis acpipci_print(void *aux, const char *pnp) 246a6e4dcfbSkettenis { 247a6e4dcfbSkettenis struct pcibus_attach_args *pba = aux; 248a6e4dcfbSkettenis 249a6e4dcfbSkettenis if (pnp) 250a6e4dcfbSkettenis printf("%s at %s", pba->pba_busname, pnp); 251a6e4dcfbSkettenis printf(" bus %d", pba->pba_bus); 252a6e4dcfbSkettenis return (UNCONF); 253a6e4dcfbSkettenis } 254a6e4dcfbSkettenis 255a6e4dcfbSkettenis int 256a6e4dcfbSkettenis acpipci_parse_resources(int crsidx, union acpi_resource *crs, void *arg) 257a6e4dcfbSkettenis { 258a6e4dcfbSkettenis struct acpipci_softc *sc = arg; 259a6e4dcfbSkettenis int type = AML_CRSTYPE(crs); 260a6e4dcfbSkettenis int restype, tflags = 0; 261a6e4dcfbSkettenis u_long min, len = 0, tra = 0; 262a6e4dcfbSkettenis 263a6e4dcfbSkettenis switch (type) { 264a6e4dcfbSkettenis case LR_WORD: 265a6e4dcfbSkettenis restype = crs->lr_word.type; 266a6e4dcfbSkettenis tflags = crs->lr_word.tflags; 267a6e4dcfbSkettenis min = crs->lr_word._min; 268a6e4dcfbSkettenis len = crs->lr_word._len; 269a6e4dcfbSkettenis tra = crs->lr_word._tra; 270a6e4dcfbSkettenis break; 271a6e4dcfbSkettenis case LR_DWORD: 272a6e4dcfbSkettenis restype = crs->lr_dword.type; 273a6e4dcfbSkettenis tflags = crs->lr_dword.tflags; 274a6e4dcfbSkettenis min = crs->lr_dword._min; 275a6e4dcfbSkettenis len = crs->lr_dword._len; 276a6e4dcfbSkettenis tra = crs->lr_dword._tra; 277a6e4dcfbSkettenis break; 278a6e4dcfbSkettenis case LR_QWORD: 279a6e4dcfbSkettenis restype = crs->lr_qword.type; 280a6e4dcfbSkettenis tflags = crs->lr_qword.tflags; 281a6e4dcfbSkettenis min = crs->lr_qword._min; 282a6e4dcfbSkettenis len = crs->lr_qword._len; 283a6e4dcfbSkettenis tra = crs->lr_qword._tra; 284a6e4dcfbSkettenis break; 285a6e4dcfbSkettenis case LR_MEM32FIXED: 286a6e4dcfbSkettenis /* 287a6e4dcfbSkettenis * Coreboot on the PC Engines apu2 incorrectly uses a 288a6e4dcfbSkettenis * Memory32Fixed resource descriptor to describe mmio 289a6e4dcfbSkettenis * address space forwarded to the PCI bus. 290a6e4dcfbSkettenis */ 291a6e4dcfbSkettenis restype = LR_TYPE_MEMORY; 292a6e4dcfbSkettenis min = crs->lr_m32fixed._bas; 293a6e4dcfbSkettenis len = crs->lr_m32fixed._len; 294a6e4dcfbSkettenis break; 295a6e4dcfbSkettenis } 296a6e4dcfbSkettenis 297a6e4dcfbSkettenis if (len == 0) 298a6e4dcfbSkettenis return 0; 299a6e4dcfbSkettenis 300a6e4dcfbSkettenis switch (restype) { 301a6e4dcfbSkettenis case LR_TYPE_MEMORY: 302a6e4dcfbSkettenis if (tflags & LR_MEMORY_TTP) 303a6e4dcfbSkettenis return 0; 304a6e4dcfbSkettenis extent_free(sc->sc_memex, min, len, EX_WAITOK | EX_CONFLICTOK); 305a6e4dcfbSkettenis break; 306a6e4dcfbSkettenis case LR_TYPE_IO: 307a6e4dcfbSkettenis if (tflags & LR_IO_TTP) 308a6e4dcfbSkettenis return 0; 309a6e4dcfbSkettenis extent_free(sc->sc_ioex, min, len, EX_WAITOK | EX_CONFLICTOK); 310a6e4dcfbSkettenis break; 311a6e4dcfbSkettenis case LR_TYPE_BUS: 312a6e4dcfbSkettenis extent_free(sc->sc_busex, min, len, EX_WAITOK); 313a6e4dcfbSkettenis /* 314a6e4dcfbSkettenis * Let _CRS minimum bus number override _BBN. 315a6e4dcfbSkettenis */ 316a6e4dcfbSkettenis sc->sc_bus = min; 317a6e4dcfbSkettenis break; 318a6e4dcfbSkettenis } 319a6e4dcfbSkettenis 320a6e4dcfbSkettenis return 0; 321a6e4dcfbSkettenis } 322a6e4dcfbSkettenis 323a6e4dcfbSkettenis void 324a6e4dcfbSkettenis acpipci_osc(struct acpipci_softc *sc) 325a6e4dcfbSkettenis { 326a6e4dcfbSkettenis struct aml_value args[4]; 327a6e4dcfbSkettenis struct aml_value res; 328a6e4dcfbSkettenis static uint8_t uuid[16] = ACPI_PCI_UUID; 329a6e4dcfbSkettenis uint32_t buf[3]; 330a6e4dcfbSkettenis 33103a88dc8Skettenis memset(args, 0, sizeof(args)); 33203a88dc8Skettenis args[0].type = AML_OBJTYPE_BUFFER; 33303a88dc8Skettenis args[0].v_buffer = uuid; 33403a88dc8Skettenis args[0].length = sizeof(uuid); 33503a88dc8Skettenis args[1].type = AML_OBJTYPE_INTEGER; 33603a88dc8Skettenis args[1].v_integer = 1; 33703a88dc8Skettenis args[2].type = AML_OBJTYPE_INTEGER; 33803a88dc8Skettenis args[2].v_integer = 3; 33903a88dc8Skettenis args[3].type = AML_OBJTYPE_BUFFER; 34003a88dc8Skettenis args[3].v_buffer = (uint8_t *)buf; 34103a88dc8Skettenis args[3].length = sizeof(buf); 34203a88dc8Skettenis 34303a88dc8Skettenis memset(buf, 0, sizeof(buf)); 34403a88dc8Skettenis buf[0] = 0x0; 34503a88dc8Skettenis buf[1] = ACPI_PCI_PCIE_CONFIG | ACPI_PCI_MSI; 34603a88dc8Skettenis buf[2] = ACPI_PCI_PCIE_HOTPLUG; 34703a88dc8Skettenis 348a6e4dcfbSkettenis if (aml_evalname(sc->sc_acpi, sc->sc_node, "_OSC", 4, args, &res)) 34903a88dc8Skettenis return; 35003a88dc8Skettenis 35103a88dc8Skettenis if (res.type == AML_OBJTYPE_BUFFER) { 35203a88dc8Skettenis size_t len = res.length; 35303a88dc8Skettenis uint32_t *p = (uint32_t *)res.v_buffer; 35403a88dc8Skettenis 35503a88dc8Skettenis printf(":"); 35603a88dc8Skettenis while (len >= 4) { 35703a88dc8Skettenis printf(" 0x%08x", *p); 35803a88dc8Skettenis p++; 35903a88dc8Skettenis len -= 4; 36003a88dc8Skettenis } 36103a88dc8Skettenis } 36203a88dc8Skettenis } 363