1 /* $NetBSD: aml_region.c,v 1.1 2007/01/14 04:36:13 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@FreeBSD.org> 5 * Copyright (c) 2000 Munehiro Matsuda <haro@tk.kubota.co.jp> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * Id: aml_region.c,v 1.10 2000/08/09 14:47:44 iwasaki Exp 30 * $FreeBSD: src/usr.sbin/acpi/amldb/aml/aml_region.c,v 1.5 2000/11/09 06:24:45 iwasaki Exp $ 31 */ 32 #include <sys/cdefs.h> 33 __RCSID("$NetBSD: aml_region.c,v 1.1 2007/01/14 04:36:13 christos Exp $"); 34 35 /* 36 * Region I/O subroutine 37 */ 38 39 #include "opt_acpi.h" 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/bus.h> 43 44 #include <machine/bus.h> 45 #include <machine/resource.h> 46 #include <sys/rman.h> 47 48 #include <dev/acpi/acpireg.h> 49 #include <dev/acpi/acpivar.h> 50 #include <aml/aml_common.h> 51 #include <aml/aml_region.h> 52 #include <aml/aml_name.h> 53 54 #ifndef ACPI_NO_OSDFUNC_INLINE 55 #include <machine/acpica_osd.h> 56 #endif 57 58 /* 59 * Dummy functions for aml_region_io_simple() 60 */ 61 u_int32_t 62 aml_region_prompt_read(struct aml_region_handle *h, u_int32_t value) 63 { 64 65 return (value); 66 } 67 68 u_int32_t 69 aml_region_prompt_write(struct aml_region_handle *h, u_int32_t value) 70 { 71 72 return (value); 73 } 74 75 int 76 aml_region_prompt_update_value(u_int32_t orgval, u_int32_t value, 77 struct aml_region_handle *h) 78 { 79 return (0); 80 } 81 82 /* 83 * Primitive functions for aml_region_io_simple() 84 */ 85 int 86 aml_region_read_simple(struct aml_region_handle *h, vm_offset_t offset, u_int32_t *valuep) 87 { 88 u_int32_t value; 89 90 switch (h->regtype) { 91 case AML_REGION_SYSMEM: 92 /* XXX should be MI */ 93 switch (h->unit) { 94 case 1: 95 value = *(volatile u_int8_t *)(h->vaddr + offset); 96 value &= 0xff; 97 break; 98 case 2: 99 value = *(volatile u_int16_t *)(h->vaddr + offset); 100 value &= 0xffff; 101 break; 102 case 4: 103 value = *(volatile u_int32_t *)(h->vaddr + offset); 104 break; 105 } 106 break; 107 case AML_REGION_SYSIO: 108 switch (h->unit) { 109 case 1: 110 value = OsdIn8(h->addr + offset); 111 value &= 0xff; 112 break; 113 case 2: 114 value = OsdIn16(h->addr + offset); 115 value &= 0xffff; 116 break; 117 case 4: 118 value = OsdIn32(h->addr + offset); 119 break; 120 } 121 break; 122 case AML_REGION_PCICFG: 123 switch (h->unit) { 124 case 1: 125 OsdReadPciCfgByte(h->pci_bus, h->pci_devfunc, 126 h->addr + offset, (UINT8 *)&value); 127 value &= 0xff; 128 break; 129 case 2: 130 OsdReadPciCfgWord(h->pci_bus, h->pci_devfunc, 131 h->addr + offset, (UINT16 *)&value); 132 value &= 0xffff; 133 break; 134 case 4: 135 OsdReadPciCfgDword(h->pci_bus, h->pci_devfunc, 136 h->addr + offset, &value); 137 break; 138 } 139 break; 140 default: 141 printf("aml_region_read_simple: not supported yet (%d)\n", 142 h->regtype); 143 value = 0; 144 break; 145 } 146 *valuep = value; 147 return (0); 148 } 149 150 int 151 aml_region_write_simple(struct aml_region_handle *h, vm_offset_t offset, u_int32_t value) 152 { 153 154 switch (h->regtype) { 155 case AML_REGION_SYSMEM: 156 /* XXX should be MI */ 157 switch (h->unit) { 158 case 1: 159 value &= 0xff; 160 *(volatile u_int8_t *)(h->vaddr + offset) = value; 161 break; 162 case 2: 163 value &= 0xffff; 164 *(volatile u_int16_t *)(h->vaddr + offset) = value; 165 break; 166 case 4: 167 *(volatile u_int32_t *)(h->vaddr + offset) = value; 168 break; 169 } 170 break; 171 case AML_REGION_SYSIO: 172 switch (h->unit) { 173 case 1: 174 value &= 0xff; 175 OsdOut8(h->addr + offset, value); 176 break; 177 case 2: 178 value &= 0xffff; 179 OsdOut16(h->addr + offset, value); 180 break; 181 case 4: 182 OsdOut32(h->addr + offset, value); 183 break; 184 } 185 break; 186 case AML_REGION_PCICFG: 187 switch (h->unit) { 188 case 1: 189 OsdWritePciCfgByte(h->pci_bus, h->pci_devfunc, 190 h->addr + offset, value); 191 break; 192 case 2: 193 OsdWritePciCfgWord(h->pci_bus, h->pci_devfunc, 194 h->addr + offset, value); 195 break; 196 case 4: 197 OsdWritePciCfgDword(h->pci_bus, h->pci_devfunc, 198 h->addr + offset, value); 199 break; 200 } 201 break; 202 default: 203 printf("aml_region_write_simple: not supported yet (%d)\n", 204 h->regtype); 205 break; 206 } 207 208 return (0); 209 } 210 211 static int 212 aml_region_io_buffer(boolean_t io, int regtype, u_int32_t flags, 213 u_int8_t *buffer, u_int32_t baseaddr, u_int32_t bitoffset, u_int32_t bitlen) 214 { 215 vm_offset_t addr, vaddr; 216 size_t len; 217 const char *funcname[] = { 218 "aml_region_read_into_buffer", 219 "aml_region_write_from_buffer" 220 }; 221 222 if (regtype != AML_REGION_SYSMEM) { 223 printf("%s: region type isn't system memory!\n", funcname[io]); 224 return (-1); 225 } 226 227 if (bitlen % 8) { 228 printf("%s: bit length isn't a multiple of 8!\n", funcname[io]); 229 } 230 if (bitoffset % 8) { 231 printf("%s: bit offset isn't a multiple of 8!\n", funcname[io]); 232 } 233 234 addr = baseaddr + bitoffset / 8; 235 len = bitlen / 8 + ((bitlen % 8) ? 1 : 0); 236 237 OsdMapMemory((void *)addr, len, (void **)&vaddr); 238 239 switch (io) { 240 case AML_REGION_INPUT: 241 bcopy((void *)vaddr, (void *)buffer, len); 242 break; 243 case AML_REGION_OUTPUT: 244 bcopy((void *)buffer, (void *)vaddr, len); 245 break; 246 } 247 248 OsdUnMapMemory((void *)vaddr, len); 249 250 return (0); 251 } 252 253 u_int32_t 254 aml_region_read(struct aml_environ *env, int regtype, u_int32_t flags, 255 u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen) 256 { 257 int value; 258 int state; 259 260 AML_REGION_READ_DEBUG(regtype, flags, addr, bitoffset, bitlen); 261 262 state = aml_region_io(env, AML_REGION_INPUT, regtype, 263 flags, &value, addr, bitoffset, bitlen); 264 AML_SYSASSERT(state != -1); 265 266 return (value); 267 } 268 269 int 270 aml_region_read_into_buffer(struct aml_environ *env, int regtype, 271 u_int32_t flags, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen, 272 u_int8_t *buffer) 273 { 274 int state; 275 276 AML_REGION_READ_INTO_BUFFER_DEBUG(regtype, flags, addr, bitoffset, bitlen); 277 state = aml_region_io_buffer(AML_REGION_INPUT, regtype, flags, 278 buffer, addr, bitoffset, bitlen); 279 280 return (state); 281 } 282 283 int 284 aml_region_write(struct aml_environ *env, int regtype, u_int32_t flags, 285 u_int32_t value, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen) 286 { 287 int state; 288 289 AML_REGION_WRITE_DEBUG(regtype, flags, value, addr, bitoffset, bitlen); 290 291 state = aml_region_io(env, AML_REGION_OUTPUT, regtype, 292 flags, &value, addr, bitoffset, bitlen); 293 AML_SYSASSERT(state != -1); 294 295 return (state); 296 } 297 298 int 299 aml_region_write_from_buffer(struct aml_environ *env, int regtype, 300 u_int32_t flags, u_int8_t *buffer, u_int32_t addr, u_int32_t bitoffset, 301 u_int32_t bitlen) 302 { 303 int state; 304 305 AML_REGION_WRITE_FROM_BUFFER_DEBUG(regtype, flags, 306 addr, bitoffset, bitlen); 307 308 state = aml_region_io_buffer(AML_REGION_OUTPUT, regtype, flags, 309 buffer, addr, bitoffset, bitlen); 310 311 return (state); 312 } 313 314 int 315 aml_region_bcopy(struct aml_environ *env, int regtype, 316 u_int32_t flags, u_int32_t addr, u_int32_t bitoffset, u_int32_t bitlen, 317 u_int32_t dflags, u_int32_t daddr, u_int32_t dbitoffset, u_int32_t dbitlen) 318 { 319 vm_offset_t from_addr, from_vaddr; 320 vm_offset_t to_addr, to_vaddr; 321 size_t len; 322 323 AML_REGION_BCOPY_DEBUG(regtype, flags, addr, bitoffset, bitlen, 324 dflags, daddr, dbitoffset, dbitlen); 325 326 if (regtype != AML_REGION_SYSMEM) { 327 printf("aml_region_bcopy: region type isn't system memory!\n"); 328 return (-1); 329 } 330 331 if ((bitlen % 8) || (dbitlen % 8)) { 332 printf("aml_region_bcopy: bit length isn't a multiple of 8!\n"); 333 } 334 if ((bitoffset % 8) || (dbitoffset % 8)) { 335 printf("aml_region_bcopy: bit offset isn't a multiple of 8!\n"); 336 } 337 338 from_addr = addr + bitoffset / 8; 339 to_addr = daddr + dbitoffset / 8; 340 341 len = (bitlen > dbitlen) ? dbitlen : bitlen; 342 len = len / 8 + ((len % 8) ? 1 : 0); 343 344 OsdMapMemory((void *)from_addr, len, (void **)&from_vaddr); 345 OsdMapMemory((void *)to_addr, len, (void **)&to_vaddr); 346 347 bcopy((void *)from_vaddr, (void *)to_vaddr, len); 348 349 OsdUnMapMemory((void *)from_vaddr, len); 350 OsdUnMapMemory((void *)to_vaddr, len); 351 352 return (0); 353 } 354