upci.c
1 /************************************************************************* 2 3 Copyright (C) 2007 John Kasunich (jmkasunich at fastmail dot fm) 4 5 This library contains functions to scan the PCI bus, find a particular 6 PCI card, and read or write memory and I/O locations on a PCI card. 7 8 ************************************************************************** 9 10 This program is free software; you can redistribute it and/or 11 modify it under the terms of version 2 of the GNU General 12 Public License as published by the Free Software Foundation. 13 This library is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public 19 License along with this library; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21 22 THE AUTHORS OF THIS LIBRARY ACCEPT ABSOLUTELY NO LIABILITY FOR 23 ANY HARM OR LOSS RESULTING FROM ITS USE. IT IS _EXTREMELY_ UNWISE 24 TO RELY ON SOFTWARE ALONE FOR SAFETY. Any machinery capable of 25 harming persons must have provisions for completely removing power 26 from all motors, etc, before persons enter any danger area. All 27 machinery must be designed to comply with local and national safety 28 codes, and the authors of this software can not, and do not, take 29 any responsibility for such compliance. 30 31 This code was written as part of the EMC HAL project. For more 32 information, go to www.linuxcnc.org. 33 34 *************************************************************************/ 35 36 #define _GNU_SOURCE /* getline() */ 37 #include <stdlib.h> 38 #include <stdio.h> 39 #include <stdarg.h> 40 #include <string.h> 41 #include <fcntl.h> 42 #include <errno.h> 43 #include <sys/types.h> 44 #include <unistd.h> 45 #include <sys/io.h> 46 #include <sys/mman.h> 47 #include <linux/types.h> 48 #include "upci.h" 49 50 /************************************************************************/ 51 52 /* Assorted typedefs */ 53 54 /* this is an standarized struct that is present in the 55 configuration space of every PCI card */ 56 struct cfg_info { 57 __u16 vendor_id; 58 __u16 device_id; 59 __u16 command; 60 __u16 status; 61 __u32 class_rev; 62 __u32 misc_0; 63 __u32 base[6]; 64 __u32 cardbus; 65 __u16 ss_vendor_id; 66 __u16 ss_device_id; 67 __u32 rom_addr; 68 __u32 reserved[2]; 69 __u32 misc_1; 70 }; 71 72 /* internal structs used by upci */ 73 struct region_info { 74 enum upci_region_type type; 75 __u32 base_addr; 76 __u32 size; 77 int region_is_mapped; 78 void *mapped_ptr; 79 }; 80 81 struct dev_info { 82 struct upci_dev_info p; /* public info */ 83 struct cfg_info cfg; /* raw data from device */ 84 struct region_info regions[6]; /* region info */ 85 }; 86 87 /************************************************************************/ 88 89 #define MAX_DEVICES 100 90 #define MAX_REGIONS (MAX_DEVICES*6) 91 92 /* we get our info from the proc filesystem */ 93 #define DEVICES_FILE "/proc/bus/pci/devices" 94 #define DEVICE_FILE "/proc/bus/pci/%02x/%02x.%01x" 95 96 /* number of discovered devices */ 97 static int num_devs = 0; 98 /* pointers to all discovered devices (others are null) */ 99 static struct dev_info *devices[MAX_DEVICES] = { NULL }; 100 /* pointers to all mapped regions (others are null) */ 101 static struct region_info *regions[MAX_REGIONS] = { NULL }; 102 /* file descriptor for /dev/mem */ 103 static int memfd = -1; 104 /* reference counters, increment each time a region is opened */ 105 static int memaccess = 0; /* non-zero if /dev/mem is open */ 106 static int ioaccess = 0; /* non-zero if iopl > 0 */ 107 108 /************************************************************************/ 109 110 static void errmsg(const char *funct, const char *fmt, ...) 111 { 112 va_list vp; 113 114 va_start(vp, fmt); 115 fprintf(stderr, "ERROR in %s(): ", funct); 116 vfprintf(stderr, fmt, vp); 117 fprintf(stderr, "\n"); 118 va_end(vp); 119 } 120 121 void upci_reset(void) 122 { 123 int d, r; 124 struct dev_info *dev; 125 struct region_info *region; 126 127 /* traverse list */ 128 for ( d = 0 ; d < num_devs ; d++ ) { 129 dev = devices[d]; 130 if ( dev != NULL ) { 131 for ( r = 0 ; r < 6 ; r++ ) { 132 region = &(dev->regions[r]); 133 if ( region->region_is_mapped ) { 134 /* unmap any mapped memory regions */ 135 munmap ( region->mapped_ptr, region->size ); 136 } 137 } 138 /* free data structures */ 139 free(dev); 140 devices[d] = NULL; 141 } 142 } 143 /* release I/O port access */ 144 if ( ioaccess ) { 145 iopl(0); 146 ioaccess = 0; 147 } 148 /* release raw memory access */ 149 if ( memaccess ) { 150 close (memfd); 151 memaccess = 0; 152 } 153 num_devs = 0; 154 } 155 156 int upci_scan_bus(void) 157 { 158 FILE *f; 159 char *lineptr; 160 size_t linelen; 161 int linenum, r, n; 162 struct dev_info *dev, *ndev; 163 struct cfg_info cfg; 164 __u32 vendordev; 165 __u16 busdevfunc; 166 char dev_fname[256]; 167 int fd; 168 169 /* delete any previous list */ 170 upci_reset(); 171 /* we use /proc as the source of all knowledge */ 172 f = fopen(DEVICES_FILE, "r"); 173 if (f == NULL) { 174 errmsg(__func__, "opening '%s': %s", DEVICES_FILE, strerror(errno)); 175 goto cleanup1; 176 } 177 lineptr = NULL; 178 linelen = 0; 179 linenum = 0; 180 while ( 1 ) { 181 if ( num_devs == MAX_DEVICES ) { 182 errmsg(__func__, "devices list full (%d entries)", num_devs); 183 /* return the ones that we already found, ignore others */ 184 free(lineptr); 185 fclose(f); 186 return num_devs; 187 } 188 /* get a line */ 189 if(getline(&lineptr, &linelen, f) < 0) { 190 /* end of file, done */ 191 free(lineptr); 192 fclose(f); 193 return num_devs; 194 } 195 ++linenum; 196 /* allocate a structure */ 197 dev = (struct dev_info *)(malloc(sizeof(struct dev_info))); 198 if ( dev == NULL ) { 199 errmsg(__func__,"malloc failure"); 200 goto cleanup2; 201 } 202 devices[num_devs++] = dev; 203 n = sscanf(lineptr, 204 "%hx %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x", 205 &busdevfunc, &vendordev, &(dev->p.irq), 206 &dev->p.base_addr[0], &dev->p.base_addr[1], &dev->p.base_addr[2], 207 &dev->p.base_addr[3], &dev->p.base_addr[4], &dev->p.base_addr[5], 208 &dev->p.rom_base_addr, 209 &dev->p.size[0], &dev->p.size[1], &dev->p.size[2], 210 &dev->p.size[3], &dev->p.size[4], &dev->p.size[5], 211 &dev->p.rom_size); 212 if (n != 17) { 213 errmsg(__func__, "only %d items on %s line %d", n, DEVICES_FILE, linenum); 214 goto cleanup3; 215 } 216 /* separate the packed fields */ 217 dev->p.vendor_id = (vendordev >> 16) & 0xFFFF; 218 dev->p.device_id = vendordev & 0xFFFF; 219 dev->p.bus = (busdevfunc >> 8) & 0x00FF; 220 dev->p.dev = (busdevfunc >> 3) & 0x001F; 221 dev->p.func = busdevfunc & 0x0007; 222 /* fix up region info: remove embedded info in low bits, 223 copy to region_info structs, init various fields */ 224 for ( r = 0 ; r < 6 ; r++ ) { 225 if ( dev->p.base_addr[r] & 1 ) { 226 /* region is I/O */ 227 dev->p.region_type[r] = UPCI_REG_IO; 228 dev->p.base_addr[r] &= ~0x03; 229 } else { 230 /* region is memory */ 231 dev->p.region_type[r] = UPCI_REG_MEM; 232 dev->p.base_addr[r] &= ~0x0F; 233 } 234 dev->regions[r].type = dev->p.region_type[r]; 235 dev->regions[r].base_addr = dev->p.base_addr[r]; 236 dev->regions[r].size = dev->p.size[r]; 237 dev->regions[r].region_is_mapped = 0; 238 dev->regions[r].mapped_ptr = NULL; 239 } 240 /* the subsystem info isn't stored in DEVICES_FILE, need to 241 look deeper to find it */ 242 snprintf(dev_fname, 255, DEVICE_FILE, dev->p.bus, dev->p.dev, dev->p.func); 243 fd = open(dev_fname, O_RDONLY); 244 if (fd < 0) { 245 errmsg(__func__, "opening '%s': %s", dev_fname, strerror(errno)); 246 goto cleanup3; 247 } 248 n = read(fd, &cfg, sizeof(struct cfg_info)); 249 if ( n != sizeof(struct cfg_info) ) { 250 errmsg(__func__, "reading '%s': %s", dev_fname, strerror(errno)); 251 goto cleanup4; 252 } 253 close(fd); 254 dev->p.ss_vendor_id = cfg.ss_vendor_id; 255 dev->p.ss_device_id = cfg.ss_device_id; 256 dev->p.instance = 0; 257 /* look for previous devices with the same vendor, device, 258 and subsystem codes. start at end of list and work forward */ 259 n = num_devs - 2; 260 while ( n >= 0 ) { 261 ndev = devices[n]; 262 if (( dev->p.vendor_id == ndev->p.vendor_id ) && 263 ( dev->p.device_id == ndev->p.device_id ) && 264 ( dev->p.ss_vendor_id == ndev->p.ss_vendor_id ) && 265 ( dev->p.ss_device_id == ndev->p.ss_device_id )) { 266 /* found a match */ 267 dev->p.instance = ndev->p.instance + 1; 268 /* don't need to look farther */ 269 break; 270 } 271 n--; 272 } 273 } 274 /* loop never falls through, success returns from inside the loop */ 275 /* errors jump here */ 276 cleanup4: 277 close(fd); 278 cleanup3: 279 free(dev); 280 num_devs --; 281 cleanup2: 282 free(lineptr); 283 fclose(f); 284 cleanup1: 285 upci_reset(); 286 return -1; 287 } 288 289 int upci_print_device_info(int devnum) 290 { 291 struct upci_dev_info *dev; 292 int n; 293 294 if (( devnum < 0 ) || ( devnum >= num_devs )) { 295 errmsg(__func__, "device %d not found", devnum); 296 return -1; 297 } 298 dev = &(devices[devnum]->p); 299 printf("PCI device %2d at bus/device/function %02x/%02x/%01x\n", 300 devnum, dev->bus, dev->dev, dev->func ); 301 printf("Vendor/Device/SSVendor/SSDevice: %04x/%04x/%04x/%04x\n", 302 dev->vendor_id, dev->device_id, dev->ss_vendor_id, dev->ss_device_id ); 303 for ( n = 0 ; n < 6 ; n++ ) { 304 if ( dev->size[n] > 0 ) { 305 if ( dev->region_type[n] == UPCI_REG_IO ) { 306 /* I/O region */ 307 printf("Region %d: I/O %u bytes at %04x\n", 308 n, dev->size[n], dev->base_addr[n] ); 309 } else { 310 /* memory region */ 311 printf("Region %d: MEM %u bytes at %08x\n", 312 n, dev->size[n], dev->base_addr[n] ); 313 } 314 } 315 } 316 return 0; 317 } 318 319 int upci_get_device_info(struct upci_dev_info *p, int devnum) 320 { 321 if (( devnum < 0 ) || ( devnum >= num_devs )) { 322 return -1; 323 } 324 if ( p == NULL ) { 325 return -1; 326 } 327 /* copy from our private structure into the user's one */ 328 *p = devices[devnum]->p; 329 return 0; 330 } 331 332 int upci_find_device(struct upci_dev_info *p) 333 { 334 int n; 335 struct dev_info *dev; 336 337 n = 0; 338 while ( n < num_devs ) { 339 dev = devices[n]; 340 if (( dev->p.vendor_id == p->vendor_id ) && 341 ( dev->p.device_id == p->device_id ) && 342 ( dev->p.ss_vendor_id == p->ss_vendor_id ) && 343 ( dev->p.ss_device_id == p->ss_device_id ) && 344 ( dev->p.instance == p->instance )) { 345 /* found a match */ 346 return n; 347 } 348 n++; 349 } 350 return -1; 351 } 352 353 static int incr_io_usage ( void ) 354 { 355 int retval, eno; 356 357 /* make sure we can do I/O */ 358 if ( ioaccess == 0 ) { 359 /* enable access */ 360 /* this needs priviliges */ 361 if (seteuid(0) != 0) { 362 errmsg(__func__, "need root privilges (or setuid root)"); 363 return -1; 364 } 365 /* do it */ 366 retval = iopl(3); 367 eno = errno; 368 /* drop priviliges */ 369 if(seteuid(getuid()) != 0) 370 { 371 errmsg(__func__, "unable to drop root privileges"); 372 /* Don't continue past this point, because following code may 373 * execute with unexpected privileges 374 */ 375 _exit(99); 376 } 377 /* check result */ 378 if(retval < 0 || iopl(3) < 0) { 379 errmsg(__func__,"opening I/O ports: %s", strerror(eno)); 380 return -1; 381 } 382 } 383 /* increment reference count */ 384 ioaccess++; 385 return 0; 386 } 387 388 static void decr_io_usage ( void ) 389 { 390 if ( ioaccess <= 0 ) { 391 /* should not be calling decr if already zero */ 392 return; 393 } 394 /* decrement reference count */ 395 ioaccess--; 396 if ( ioaccess == 0 ) { 397 /* release I/O priveleges */ 398 iopl(0); 399 } 400 } 401 402 static int incr_mem_usage ( void ) 403 { 404 int eno; 405 406 /* make sure /dev/mem is open */ 407 if ( memaccess == 0 ) { 408 /* open it */ 409 /* this needs priviliges */ 410 if (seteuid(0) != 0) { 411 errmsg(__func__, "need root privilges (or setuid root)"); 412 return -1; 413 } 414 /* do it */ 415 memfd = open("/dev/mem", O_RDWR); 416 eno = errno; 417 /* drop priviliges */ 418 if(seteuid(getuid()) != 0) 419 { 420 errmsg(__func__, "unable to drop root privileges"); 421 /* Don't continue past this point, because following code may 422 * execute with unexpected privileges 423 */ 424 _exit(99); 425 } 426 /* check result */ 427 if ( memfd < 0 ) { 428 errmsg(__func__,"can't open /dev/mem: %s", strerror(eno)); 429 return -1; 430 } 431 } 432 /* increment reference count */ 433 memaccess++; 434 return 0; 435 } 436 437 static void decr_mem_usage ( void ) 438 { 439 if ( memaccess <= 0 ) { 440 /* should not be calling decr if already zero */ 441 return; 442 } 443 /* decrement reference count */ 444 memaccess--; 445 if ( memaccess == 0 ) { 446 /* close /dev/mem */ 447 close(memfd); 448 } 449 } 450 451 int upci_open_region(int devnum, int region_num) 452 { 453 struct dev_info *dev; 454 struct region_info *reg; 455 int rd; 456 457 if (( devnum < 0 ) || ( devnum >= num_devs )) { 458 errmsg(__func__, "device %d not found", devnum); 459 return -1; 460 } 461 dev = devices[devnum]; 462 if (( region_num < 0 ) || ( region_num >= 6 )) { 463 errmsg(__func__, "bad region number %d", region_num); 464 return -1; 465 } 466 reg = &(dev->regions[region_num]); 467 if ( reg->size == 0 ) { 468 errmsg(__func__, "region %d not found in device %d", 469 region_num, devnum); 470 return -1; 471 } 472 /* calculate region descriptor */ 473 rd = devnum * 6 + region_num; 474 if ( reg->region_is_mapped ) { 475 /* already open, nothing to do */ 476 return rd; 477 } 478 if ( reg->type == UPCI_REG_IO ) { 479 /* region is IO, no mapping needed */ 480 /* update reference counter */ 481 if ( incr_io_usage() != 0 ) { 482 errmsg(__func__, "no I/O access"); 483 return -1; 484 } 485 } else { 486 /* region is memory */ 487 /* update reference counter */ 488 if ( incr_mem_usage() != 0 ) { 489 return -1; 490 } 491 /* map the memory region */ 492 reg->mapped_ptr = mmap(0, reg->size, PROT_READ | PROT_WRITE, 493 MAP_SHARED, memfd, reg->base_addr); 494 if ( reg->mapped_ptr == MAP_FAILED ) { 495 reg->mapped_ptr = NULL; 496 errmsg(__func__, "can't map /dev/mem for device %d, region %d: %s", 497 devnum, region_num, strerror(errno)); 498 decr_mem_usage(); 499 return -1; 500 } 501 } 502 /* mark region as mapped */ 503 reg->region_is_mapped = 1; 504 regions[rd] = reg; 505 return rd; 506 } 507 508 void upci_close_region(int rd) 509 { 510 struct region_info *reg; 511 512 if ((rd < 0 ) || ( rd >= MAX_REGIONS )) return; 513 reg = regions[rd]; 514 if ( reg == NULL ) return; 515 if ( reg->type == UPCI_REG_IO ) { 516 /* region is IO, nothing to unmap */ 517 decr_io_usage(); 518 } else { 519 /* region is memory, unmap it */ 520 munmap ( reg->mapped_ptr, reg->size ); 521 decr_mem_usage(); 522 } 523 /* mark region as unmapped */ 524 reg->region_is_mapped = 0; 525 regions[rd] = NULL; 526 } 527 528 __u8 upci_read_u8(int rd, __u32 offset) 529 { 530 struct region_info *reg; 531 int port; 532 volatile __u8 *ptr, data; 533 534 /* test for out of range, not mapped, or offset beyond end of region */ 535 if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || 536 ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return 0; 537 /* get the data */ 538 if ( reg->type == UPCI_REG_IO ) { 539 /* region is IO */ 540 port = reg->base_addr + offset; 541 data = inb(port); 542 } else { 543 /* region is memory */ 544 ptr = (__u8 *)(reg->mapped_ptr + offset); 545 data = *ptr; 546 } 547 return data; 548 } 549 550 __s8 upci_read_s8(int rd, __u32 offset) 551 { 552 struct region_info *reg; 553 int port; 554 volatile __s8 *ptr, data; 555 556 /* test for out of range, not mapped, or offset beyond end of region */ 557 if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || 558 ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return 0; 559 /* get the data */ 560 if ( reg->type == UPCI_REG_IO ) { 561 port = reg->base_addr + offset; 562 data = inb(port); 563 } else { 564 ptr = (__s8 *)(reg->mapped_ptr + offset); 565 data = *ptr; 566 } 567 return data; 568 } 569 570 __u16 upci_read_u16(int rd, __u32 offset) 571 { 572 struct region_info *reg; 573 int port; 574 volatile __u16 *ptr, data; 575 576 /* test for out of range, not mapped, or offset beyond end of region */ 577 if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || 578 ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return 0; 579 /* get the data */ 580 if ( reg->type == UPCI_REG_IO ) { 581 port = reg->base_addr + offset; 582 data = inw(port); 583 } else { 584 ptr = (__u16 *)(reg->mapped_ptr + offset); 585 data = *ptr; 586 } 587 return data; 588 } 589 590 __s16 upci_read_s16(int rd, __u32 offset) 591 { 592 struct region_info *reg; 593 int port; 594 volatile __s16 *ptr, data; 595 596 /* test for out of range, not mapped, or offset beyond end of region */ 597 if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || 598 ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return 0; 599 /* get the data */ 600 if ( reg->type == UPCI_REG_IO ) { 601 port = reg->base_addr + offset; 602 data = inw(port); 603 } else { 604 ptr = (__s16 *)(reg->mapped_ptr + offset); 605 data = *ptr; 606 } 607 return data; 608 } 609 610 __u32 upci_read_u32(int rd, __u32 offset) 611 { 612 struct region_info *reg; 613 int port; 614 volatile __u32 *ptr, data; 615 616 /* test for out of range, not mapped, or offset beyond end of region */ 617 if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || 618 ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return 0; 619 /* get the data */ 620 if ( reg->type == UPCI_REG_IO ) { 621 port = reg->base_addr + offset; 622 data = inl(port); 623 } else { 624 ptr = (__u32 *)(reg->mapped_ptr + offset); 625 data = *ptr; 626 } 627 return data; 628 } 629 630 __s32 upci_read_s32(int rd, __u32 offset) 631 { 632 struct region_info *reg; 633 int port; 634 volatile __s32 *ptr, data; 635 636 /* test for out of range, not mapped, or offset beyond end of region */ 637 if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || 638 ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return 0; 639 /* get the data */ 640 if ( reg->type == UPCI_REG_IO ) { 641 port = reg->base_addr + offset; 642 data = inl(port); 643 } else { 644 ptr = (__s32 *)(reg->mapped_ptr + offset); 645 data = *ptr; 646 } 647 return data; 648 } 649 650 void upci_write_u8(int rd, __u32 offset, __u8 data) 651 { 652 struct region_info *reg; 653 int port; 654 volatile __u8 *ptr; 655 656 /* test for out of range, not mapped, or offset beyond end of region */ 657 if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || 658 ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return; 659 /* write the data */ 660 if ( reg->type == UPCI_REG_IO ) { 661 /* region is IO */ 662 port = reg->base_addr + offset; 663 outb(data, port); 664 } else { 665 /* region is memory */ 666 ptr = (__u8 *)(reg->mapped_ptr + offset); 667 *ptr = data; 668 } 669 return; 670 } 671 672 void upci_write_s8(int rd, __u32 offset, __s8 data) 673 { 674 struct region_info *reg; 675 int port; 676 volatile __s8 *ptr; 677 678 /* test for out of range, not mapped, or offset beyond end of region */ 679 if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || 680 ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return; 681 /* write the data */ 682 if ( reg->type == UPCI_REG_IO ) { 683 port = reg->base_addr + offset; 684 outb(data, port); 685 } else { 686 ptr = (__s8 *)(reg->mapped_ptr + offset); 687 *ptr = data; 688 } 689 return; 690 } 691 692 void upci_write_u16(int rd, __u32 offset, __u16 data) 693 { 694 struct region_info *reg; 695 int port; 696 volatile __u16 *ptr; 697 698 /* test for out of range, not mapped, or offset beyond end of region */ 699 if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || 700 ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return; 701 /* write the data */ 702 if ( reg->type == UPCI_REG_IO ) { 703 port = reg->base_addr + offset; 704 outw(data, port); 705 } else { 706 ptr = (__u16 *)(reg->mapped_ptr + offset); 707 *ptr = data; 708 } 709 return; 710 } 711 712 void upci_write_s16(int rd, __u32 offset, __s16 data) 713 { 714 struct region_info *reg; 715 int port; 716 volatile __s16 *ptr; 717 718 /* test for out of range, not mapped, or offset beyond end of region */ 719 if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || 720 ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return; 721 /* write the data */ 722 if ( reg->type == UPCI_REG_IO ) { 723 port = reg->base_addr + offset; 724 outw(data, port); 725 } else { 726 ptr = (__s16 *)(reg->mapped_ptr + offset); 727 *ptr = data; 728 } 729 return; 730 } 731 732 void upci_write_u32(int rd, __u32 offset, __u32 data) 733 { 734 struct region_info *reg; 735 int port; 736 volatile __u32 *ptr; 737 738 /* test for out of range, not mapped, or offset beyond end of region */ 739 if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || 740 ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return; 741 /* write the data */ 742 if ( reg->type == UPCI_REG_IO ) { 743 port = reg->base_addr + offset; 744 outl(data, port); 745 } else { 746 ptr = (__u32 *)(reg->mapped_ptr + offset); 747 *ptr = data; 748 } 749 return; 750 } 751 752 void upci_write_s32(int rd, __u32 offset, __s32 data) 753 { 754 struct region_info *reg; 755 int port; 756 volatile __s32 *ptr; 757 758 /* test for out of range, not mapped, or offset beyond end of region */ 759 if ((rd < 0 ) || ( rd >= MAX_REGIONS ) || 760 ( (reg = regions[rd]) == NULL ) || ( offset > reg->size )) return; 761 /* write the data */ 762 if ( reg->type == UPCI_REG_IO ) { 763 port = reg->base_addr + offset; 764 outl(data, port); 765 } else { 766 ptr = (__s32 *)(reg->mapped_ptr + offset); 767 *ptr = data; 768 } 769 return; 770 }