1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 1997, Stefan Esser <se@freebsd.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice unmodified, this list of conditions, and the following 12 * 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 ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 #include "opt_bus.h" /* XXX trim includes */ 33 34 #include <sys/types.h> 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/malloc.h> 38 #include <sys/module.h> 39 #include <sys/linker.h> 40 #include <sys/fcntl.h> 41 #include <sys/conf.h> 42 #include <sys/kernel.h> 43 #include <sys/mman.h> 44 #include <sys/proc.h> 45 #include <sys/queue.h> 46 #include <sys/rwlock.h> 47 #include <sys/sglist.h> 48 49 #include <vm/vm.h> 50 #include <vm/pmap.h> 51 #include <vm/vm_extern.h> 52 #include <vm/vm_map.h> 53 #include <vm/vm_object.h> 54 #include <vm/vm_page.h> 55 #include <vm/vm_pager.h> 56 57 #include <sys/bus.h> 58 #include <machine/bus.h> 59 #include <sys/rman.h> 60 #include <machine/resource.h> 61 62 #include <sys/pciio.h> 63 #include <dev/pci/pcireg.h> 64 #include <dev/pci/pcivar.h> 65 66 #include "pcib_if.h" 67 #include "pci_if.h" 68 69 /* 70 * This is the user interface to PCI configuration space. 71 */ 72 73 static d_open_t pci_open; 74 static d_close_t pci_close; 75 static d_ioctl_t pci_ioctl; 76 77 struct cdevsw pcicdev = { 78 .d_version = D_VERSION, 79 .d_flags = D_NEEDGIANT, 80 .d_open = pci_open, 81 .d_close = pci_close, 82 .d_ioctl = pci_ioctl, 83 .d_name = "pci", 84 }; 85 86 static int 87 pci_open(struct cdev *dev, int oflags, int devtype, struct thread *td) 88 { 89 int error; 90 91 if (oflags & FWRITE) { 92 error = securelevel_gt(td->td_ucred, 0); 93 if (error) 94 return (error); 95 } 96 97 return (0); 98 } 99 100 static int 101 pci_close(struct cdev *dev, int flag, int devtype, struct thread *td) 102 { 103 return 0; 104 } 105 106 /* 107 * Match a single pci_conf structure against an array of pci_match_conf 108 * structures. The first argument, 'matches', is an array of num_matches 109 * pci_match_conf structures. match_buf is a pointer to the pci_conf 110 * structure that will be compared to every entry in the matches array. 111 * This function returns 1 on failure, 0 on success. 112 */ 113 static int 114 pci_conf_match_native(struct pci_match_conf *matches, int num_matches, 115 struct pci_conf *match_buf) 116 { 117 int i; 118 119 if ((matches == NULL) || (match_buf == NULL) || (num_matches <= 0)) 120 return(1); 121 122 for (i = 0; i < num_matches; i++) { 123 /* 124 * I'm not sure why someone would do this...but... 125 */ 126 if (matches[i].flags == PCI_GETCONF_NO_MATCH) 127 continue; 128 129 /* 130 * Look at each of the match flags. If it's set, do the 131 * comparison. If the comparison fails, we don't have a 132 * match, go on to the next item if there is one. 133 */ 134 if (((matches[i].flags & PCI_GETCONF_MATCH_DOMAIN) != 0) 135 && (match_buf->pc_sel.pc_domain != 136 matches[i].pc_sel.pc_domain)) 137 continue; 138 139 if (((matches[i].flags & PCI_GETCONF_MATCH_BUS) != 0) 140 && (match_buf->pc_sel.pc_bus != matches[i].pc_sel.pc_bus)) 141 continue; 142 143 if (((matches[i].flags & PCI_GETCONF_MATCH_DEV) != 0) 144 && (match_buf->pc_sel.pc_dev != matches[i].pc_sel.pc_dev)) 145 continue; 146 147 if (((matches[i].flags & PCI_GETCONF_MATCH_FUNC) != 0) 148 && (match_buf->pc_sel.pc_func != matches[i].pc_sel.pc_func)) 149 continue; 150 151 if (((matches[i].flags & PCI_GETCONF_MATCH_VENDOR) != 0) 152 && (match_buf->pc_vendor != matches[i].pc_vendor)) 153 continue; 154 155 if (((matches[i].flags & PCI_GETCONF_MATCH_DEVICE) != 0) 156 && (match_buf->pc_device != matches[i].pc_device)) 157 continue; 158 159 if (((matches[i].flags & PCI_GETCONF_MATCH_CLASS) != 0) 160 && (match_buf->pc_class != matches[i].pc_class)) 161 continue; 162 163 if (((matches[i].flags & PCI_GETCONF_MATCH_UNIT) != 0) 164 && (match_buf->pd_unit != matches[i].pd_unit)) 165 continue; 166 167 if (((matches[i].flags & PCI_GETCONF_MATCH_NAME) != 0) 168 && (strncmp(matches[i].pd_name, match_buf->pd_name, 169 sizeof(match_buf->pd_name)) != 0)) 170 continue; 171 172 return(0); 173 } 174 175 return(1); 176 } 177 178 #if defined(COMPAT_FREEBSD4) || defined(COMPAT_FREEBSD5) || \ 179 defined(COMPAT_FREEBSD6) 180 #define PRE7_COMPAT 181 182 typedef enum { 183 PCI_GETCONF_NO_MATCH_OLD = 0x00, 184 PCI_GETCONF_MATCH_BUS_OLD = 0x01, 185 PCI_GETCONF_MATCH_DEV_OLD = 0x02, 186 PCI_GETCONF_MATCH_FUNC_OLD = 0x04, 187 PCI_GETCONF_MATCH_NAME_OLD = 0x08, 188 PCI_GETCONF_MATCH_UNIT_OLD = 0x10, 189 PCI_GETCONF_MATCH_VENDOR_OLD = 0x20, 190 PCI_GETCONF_MATCH_DEVICE_OLD = 0x40, 191 PCI_GETCONF_MATCH_CLASS_OLD = 0x80 192 } pci_getconf_flags_old; 193 194 struct pcisel_old { 195 u_int8_t pc_bus; /* bus number */ 196 u_int8_t pc_dev; /* device on this bus */ 197 u_int8_t pc_func; /* function on this device */ 198 }; 199 200 struct pci_conf_old { 201 struct pcisel_old pc_sel; /* bus+slot+function */ 202 u_int8_t pc_hdr; /* PCI header type */ 203 u_int16_t pc_subvendor; /* card vendor ID */ 204 u_int16_t pc_subdevice; /* card device ID, assigned by 205 card vendor */ 206 u_int16_t pc_vendor; /* chip vendor ID */ 207 u_int16_t pc_device; /* chip device ID, assigned by 208 chip vendor */ 209 u_int8_t pc_class; /* chip PCI class */ 210 u_int8_t pc_subclass; /* chip PCI subclass */ 211 u_int8_t pc_progif; /* chip PCI programming interface */ 212 u_int8_t pc_revid; /* chip revision ID */ 213 char pd_name[PCI_MAXNAMELEN + 1]; /* device name */ 214 u_long pd_unit; /* device unit number */ 215 }; 216 217 struct pci_match_conf_old { 218 struct pcisel_old pc_sel; /* bus+slot+function */ 219 char pd_name[PCI_MAXNAMELEN + 1]; /* device name */ 220 u_long pd_unit; /* Unit number */ 221 u_int16_t pc_vendor; /* PCI Vendor ID */ 222 u_int16_t pc_device; /* PCI Device ID */ 223 u_int8_t pc_class; /* PCI class */ 224 pci_getconf_flags_old flags; /* Matching expression */ 225 }; 226 227 struct pci_io_old { 228 struct pcisel_old pi_sel; /* device to operate on */ 229 int pi_reg; /* configuration register to examine */ 230 int pi_width; /* width (in bytes) of read or write */ 231 u_int32_t pi_data; /* data to write or result of read */ 232 }; 233 234 #ifdef COMPAT_FREEBSD32 235 struct pci_conf_old32 { 236 struct pcisel_old pc_sel; /* bus+slot+function */ 237 uint8_t pc_hdr; /* PCI header type */ 238 uint16_t pc_subvendor; /* card vendor ID */ 239 uint16_t pc_subdevice; /* card device ID, assigned by 240 card vendor */ 241 uint16_t pc_vendor; /* chip vendor ID */ 242 uint16_t pc_device; /* chip device ID, assigned by 243 chip vendor */ 244 uint8_t pc_class; /* chip PCI class */ 245 uint8_t pc_subclass; /* chip PCI subclass */ 246 uint8_t pc_progif; /* chip PCI programming interface */ 247 uint8_t pc_revid; /* chip revision ID */ 248 char pd_name[PCI_MAXNAMELEN + 1]; /* device name */ 249 uint32_t pd_unit; /* device unit number (u_long) */ 250 }; 251 252 struct pci_match_conf_old32 { 253 struct pcisel_old pc_sel; /* bus+slot+function */ 254 char pd_name[PCI_MAXNAMELEN + 1]; /* device name */ 255 uint32_t pd_unit; /* Unit number (u_long) */ 256 uint16_t pc_vendor; /* PCI Vendor ID */ 257 uint16_t pc_device; /* PCI Device ID */ 258 uint8_t pc_class; /* PCI class */ 259 pci_getconf_flags_old flags; /* Matching expression */ 260 }; 261 262 struct pci_conf_io32 { 263 uint32_t pat_buf_len; /* pattern buffer length */ 264 uint32_t num_patterns; /* number of patterns */ 265 uint32_t patterns; /* pattern buffer 266 (struct pci_match_conf_old32 *) */ 267 uint32_t match_buf_len; /* match buffer length */ 268 uint32_t num_matches; /* number of matches returned */ 269 uint32_t matches; /* match buffer 270 (struct pci_conf_old32 *) */ 271 uint32_t offset; /* offset into device list */ 272 uint32_t generation; /* device list generation */ 273 pci_getconf_status status; /* request status */ 274 }; 275 276 #define PCIOCGETCONF_OLD32 _IOWR('p', 1, struct pci_conf_io32) 277 #endif /* COMPAT_FREEBSD32 */ 278 279 #define PCIOCGETCONF_OLD _IOWR('p', 1, struct pci_conf_io) 280 #define PCIOCREAD_OLD _IOWR('p', 2, struct pci_io_old) 281 #define PCIOCWRITE_OLD _IOWR('p', 3, struct pci_io_old) 282 283 static int 284 pci_conf_match_old(struct pci_match_conf_old *matches, int num_matches, 285 struct pci_conf *match_buf) 286 { 287 int i; 288 289 if ((matches == NULL) || (match_buf == NULL) || (num_matches <= 0)) 290 return(1); 291 292 for (i = 0; i < num_matches; i++) { 293 if (match_buf->pc_sel.pc_domain != 0) 294 continue; 295 296 /* 297 * I'm not sure why someone would do this...but... 298 */ 299 if (matches[i].flags == PCI_GETCONF_NO_MATCH_OLD) 300 continue; 301 302 /* 303 * Look at each of the match flags. If it's set, do the 304 * comparison. If the comparison fails, we don't have a 305 * match, go on to the next item if there is one. 306 */ 307 if (((matches[i].flags & PCI_GETCONF_MATCH_BUS_OLD) != 0) 308 && (match_buf->pc_sel.pc_bus != matches[i].pc_sel.pc_bus)) 309 continue; 310 311 if (((matches[i].flags & PCI_GETCONF_MATCH_DEV_OLD) != 0) 312 && (match_buf->pc_sel.pc_dev != matches[i].pc_sel.pc_dev)) 313 continue; 314 315 if (((matches[i].flags & PCI_GETCONF_MATCH_FUNC_OLD) != 0) 316 && (match_buf->pc_sel.pc_func != matches[i].pc_sel.pc_func)) 317 continue; 318 319 if (((matches[i].flags & PCI_GETCONF_MATCH_VENDOR_OLD) != 0) 320 && (match_buf->pc_vendor != matches[i].pc_vendor)) 321 continue; 322 323 if (((matches[i].flags & PCI_GETCONF_MATCH_DEVICE_OLD) != 0) 324 && (match_buf->pc_device != matches[i].pc_device)) 325 continue; 326 327 if (((matches[i].flags & PCI_GETCONF_MATCH_CLASS_OLD) != 0) 328 && (match_buf->pc_class != matches[i].pc_class)) 329 continue; 330 331 if (((matches[i].flags & PCI_GETCONF_MATCH_UNIT_OLD) != 0) 332 && (match_buf->pd_unit != matches[i].pd_unit)) 333 continue; 334 335 if (((matches[i].flags & PCI_GETCONF_MATCH_NAME_OLD) != 0) 336 && (strncmp(matches[i].pd_name, match_buf->pd_name, 337 sizeof(match_buf->pd_name)) != 0)) 338 continue; 339 340 return(0); 341 } 342 343 return(1); 344 } 345 346 #ifdef COMPAT_FREEBSD32 347 static int 348 pci_conf_match_old32(struct pci_match_conf_old32 *matches, int num_matches, 349 struct pci_conf *match_buf) 350 { 351 int i; 352 353 if ((matches == NULL) || (match_buf == NULL) || (num_matches <= 0)) 354 return(1); 355 356 for (i = 0; i < num_matches; i++) { 357 if (match_buf->pc_sel.pc_domain != 0) 358 continue; 359 360 /* 361 * I'm not sure why someone would do this...but... 362 */ 363 if (matches[i].flags == PCI_GETCONF_NO_MATCH_OLD) 364 continue; 365 366 /* 367 * Look at each of the match flags. If it's set, do the 368 * comparison. If the comparison fails, we don't have a 369 * match, go on to the next item if there is one. 370 */ 371 if (((matches[i].flags & PCI_GETCONF_MATCH_BUS_OLD) != 0) && 372 (match_buf->pc_sel.pc_bus != matches[i].pc_sel.pc_bus)) 373 continue; 374 375 if (((matches[i].flags & PCI_GETCONF_MATCH_DEV_OLD) != 0) && 376 (match_buf->pc_sel.pc_dev != matches[i].pc_sel.pc_dev)) 377 continue; 378 379 if (((matches[i].flags & PCI_GETCONF_MATCH_FUNC_OLD) != 0) && 380 (match_buf->pc_sel.pc_func != matches[i].pc_sel.pc_func)) 381 continue; 382 383 if (((matches[i].flags & PCI_GETCONF_MATCH_VENDOR_OLD) != 0) && 384 (match_buf->pc_vendor != matches[i].pc_vendor)) 385 continue; 386 387 if (((matches[i].flags & PCI_GETCONF_MATCH_DEVICE_OLD) != 0) && 388 (match_buf->pc_device != matches[i].pc_device)) 389 continue; 390 391 if (((matches[i].flags & PCI_GETCONF_MATCH_CLASS_OLD) != 0) && 392 (match_buf->pc_class != matches[i].pc_class)) 393 continue; 394 395 if (((matches[i].flags & PCI_GETCONF_MATCH_UNIT_OLD) != 0) && 396 ((u_int32_t)match_buf->pd_unit != matches[i].pd_unit)) 397 continue; 398 399 if (((matches[i].flags & PCI_GETCONF_MATCH_NAME_OLD) != 0) && 400 (strncmp(matches[i].pd_name, match_buf->pd_name, 401 sizeof(match_buf->pd_name)) != 0)) 402 continue; 403 404 return (0); 405 } 406 407 return (1); 408 } 409 #endif /* COMPAT_FREEBSD32 */ 410 #endif /* !PRE7_COMPAT */ 411 412 union pci_conf_union { 413 struct pci_conf pc; 414 #ifdef PRE7_COMPAT 415 struct pci_conf_old pco; 416 #ifdef COMPAT_FREEBSD32 417 struct pci_conf_old32 pco32; 418 #endif 419 #endif 420 }; 421 422 static int 423 pci_conf_match(u_long cmd, struct pci_match_conf *matches, int num_matches, 424 struct pci_conf *match_buf) 425 { 426 427 switch (cmd) { 428 case PCIOCGETCONF: 429 return (pci_conf_match_native( 430 (struct pci_match_conf *)matches, num_matches, match_buf)); 431 #ifdef PRE7_COMPAT 432 case PCIOCGETCONF_OLD: 433 return (pci_conf_match_old( 434 (struct pci_match_conf_old *)matches, num_matches, 435 match_buf)); 436 #ifdef COMPAT_FREEBSD32 437 case PCIOCGETCONF_OLD32: 438 return (pci_conf_match_old32( 439 (struct pci_match_conf_old32 *)matches, num_matches, 440 match_buf)); 441 #endif 442 #endif 443 default: 444 /* programmer error */ 445 return (0); 446 } 447 } 448 449 /* 450 * Like PVE_NEXT but takes an explicit length since 'pve' is a user 451 * pointer that cannot be dereferenced. 452 */ 453 #define PVE_NEXT_LEN(pve, datalen) \ 454 ((struct pci_vpd_element *)((char *)(pve) + \ 455 sizeof(struct pci_vpd_element) + (datalen))) 456 457 static int 458 pci_list_vpd(device_t dev, struct pci_list_vpd_io *lvio) 459 { 460 struct pci_vpd_element vpd_element, *vpd_user; 461 struct pcicfg_vpd *vpd; 462 size_t len; 463 int error, i; 464 465 vpd = pci_fetch_vpd_list(dev); 466 if (vpd->vpd_reg == 0 || vpd->vpd_ident == NULL) 467 return (ENXIO); 468 469 /* 470 * Calculate the amount of space needed in the data buffer. An 471 * identifier element is always present followed by the read-only 472 * and read-write keywords. 473 */ 474 len = sizeof(struct pci_vpd_element) + strlen(vpd->vpd_ident); 475 for (i = 0; i < vpd->vpd_rocnt; i++) 476 len += sizeof(struct pci_vpd_element) + vpd->vpd_ros[i].len; 477 for (i = 0; i < vpd->vpd_wcnt; i++) 478 len += sizeof(struct pci_vpd_element) + vpd->vpd_w[i].len; 479 480 if (lvio->plvi_len == 0) { 481 lvio->plvi_len = len; 482 return (0); 483 } 484 if (lvio->plvi_len < len) { 485 lvio->plvi_len = len; 486 return (ENOMEM); 487 } 488 489 /* 490 * Copyout the identifier string followed by each keyword and 491 * value. 492 */ 493 vpd_user = lvio->plvi_data; 494 vpd_element.pve_keyword[0] = '\0'; 495 vpd_element.pve_keyword[1] = '\0'; 496 vpd_element.pve_flags = PVE_FLAG_IDENT; 497 vpd_element.pve_datalen = strlen(vpd->vpd_ident); 498 error = copyout(&vpd_element, vpd_user, sizeof(vpd_element)); 499 if (error) 500 return (error); 501 error = copyout(vpd->vpd_ident, vpd_user->pve_data, 502 strlen(vpd->vpd_ident)); 503 if (error) 504 return (error); 505 vpd_user = PVE_NEXT_LEN(vpd_user, vpd_element.pve_datalen); 506 vpd_element.pve_flags = 0; 507 for (i = 0; i < vpd->vpd_rocnt; i++) { 508 vpd_element.pve_keyword[0] = vpd->vpd_ros[i].keyword[0]; 509 vpd_element.pve_keyword[1] = vpd->vpd_ros[i].keyword[1]; 510 vpd_element.pve_datalen = vpd->vpd_ros[i].len; 511 error = copyout(&vpd_element, vpd_user, sizeof(vpd_element)); 512 if (error) 513 return (error); 514 error = copyout(vpd->vpd_ros[i].value, vpd_user->pve_data, 515 vpd->vpd_ros[i].len); 516 if (error) 517 return (error); 518 vpd_user = PVE_NEXT_LEN(vpd_user, vpd_element.pve_datalen); 519 } 520 vpd_element.pve_flags = PVE_FLAG_RW; 521 for (i = 0; i < vpd->vpd_wcnt; i++) { 522 vpd_element.pve_keyword[0] = vpd->vpd_w[i].keyword[0]; 523 vpd_element.pve_keyword[1] = vpd->vpd_w[i].keyword[1]; 524 vpd_element.pve_datalen = vpd->vpd_w[i].len; 525 error = copyout(&vpd_element, vpd_user, sizeof(vpd_element)); 526 if (error) 527 return (error); 528 error = copyout(vpd->vpd_w[i].value, vpd_user->pve_data, 529 vpd->vpd_w[i].len); 530 if (error) 531 return (error); 532 vpd_user = PVE_NEXT_LEN(vpd_user, vpd_element.pve_datalen); 533 } 534 KASSERT((char *)vpd_user - (char *)lvio->plvi_data == len, 535 ("length mismatch")); 536 lvio->plvi_len = len; 537 return (0); 538 } 539 540 static size_t 541 pci_match_conf_size(u_long cmd) 542 { 543 544 switch (cmd) { 545 case PCIOCGETCONF: 546 return (sizeof(struct pci_match_conf)); 547 #ifdef PRE7_COMPAT 548 case PCIOCGETCONF_OLD: 549 return (sizeof(struct pci_match_conf_old)); 550 #ifdef COMPAT_FREEBSD32 551 case PCIOCGETCONF_OLD32: 552 return (sizeof(struct pci_match_conf_old32)); 553 #endif 554 #endif 555 default: 556 /* programmer error */ 557 return (0); 558 } 559 } 560 561 static size_t 562 pci_conf_size(u_long cmd) 563 { 564 565 switch (cmd) { 566 case PCIOCGETCONF: 567 return (sizeof(struct pci_conf)); 568 #ifdef PRE7_COMPAT 569 case PCIOCGETCONF_OLD: 570 return (sizeof(struct pci_conf_old)); 571 #ifdef COMPAT_FREEBSD32 572 case PCIOCGETCONF_OLD32: 573 return (sizeof(struct pci_conf_old32)); 574 #endif 575 #endif 576 default: 577 /* programmer error */ 578 return (0); 579 } 580 } 581 582 static void 583 pci_conf_io_init(struct pci_conf_io *cio, caddr_t data, u_long cmd) 584 { 585 #if defined(PRE7_COMPAT) && defined(COMPAT_FREEBSD32) 586 struct pci_conf_io32 *cio32; 587 #endif 588 589 switch (cmd) { 590 case PCIOCGETCONF: 591 #ifdef PRE7_COMPAT 592 case PCIOCGETCONF_OLD: 593 #endif 594 *cio = *(struct pci_conf_io *)data; 595 return; 596 597 #if defined(PRE7_COMPAT) && defined(COMPAT_FREEBSD32) 598 case PCIOCGETCONF_OLD32: 599 cio32 = (struct pci_conf_io32 *)data; 600 cio->pat_buf_len = cio32->pat_buf_len; 601 cio->num_patterns = cio32->num_patterns; 602 cio->patterns = (void *)(uintptr_t)cio32->patterns; 603 cio->match_buf_len = cio32->match_buf_len; 604 cio->num_matches = cio32->num_matches; 605 cio->matches = (void *)(uintptr_t)cio32->matches; 606 cio->offset = cio32->offset; 607 cio->generation = cio32->generation; 608 cio->status = cio32->status; 609 return; 610 #endif 611 612 default: 613 /* programmer error */ 614 return; 615 } 616 } 617 618 static void 619 pci_conf_io_update_data(const struct pci_conf_io *cio, caddr_t data, 620 u_long cmd) 621 { 622 struct pci_conf_io *d_cio; 623 #if defined(PRE7_COMPAT) && defined(COMPAT_FREEBSD32) 624 struct pci_conf_io32 *cio32; 625 #endif 626 627 switch (cmd) { 628 case PCIOCGETCONF: 629 #ifdef PRE7_COMPAT 630 case PCIOCGETCONF_OLD: 631 #endif 632 d_cio = (struct pci_conf_io *)data; 633 d_cio->status = cio->status; 634 d_cio->generation = cio->generation; 635 d_cio->offset = cio->offset; 636 d_cio->num_matches = cio->num_matches; 637 return; 638 639 #if defined(PRE7_COMPAT) && defined(COMPAT_FREEBSD32) 640 case PCIOCGETCONF_OLD32: 641 cio32 = (struct pci_conf_io32 *)data; 642 643 cio32->status = cio->status; 644 cio32->generation = cio->generation; 645 cio32->offset = cio->offset; 646 cio32->num_matches = cio->num_matches; 647 return; 648 #endif 649 650 default: 651 /* programmer error */ 652 return; 653 } 654 } 655 656 static void 657 pci_conf_for_copyout(const struct pci_conf *pcp, union pci_conf_union *pcup, 658 u_long cmd) 659 { 660 661 memset(pcup, 0, sizeof(*pcup)); 662 663 switch (cmd) { 664 case PCIOCGETCONF: 665 pcup->pc = *pcp; 666 return; 667 668 #ifdef PRE7_COMPAT 669 #ifdef COMPAT_FREEBSD32 670 case PCIOCGETCONF_OLD32: 671 pcup->pco32.pc_sel.pc_bus = pcp->pc_sel.pc_bus; 672 pcup->pco32.pc_sel.pc_dev = pcp->pc_sel.pc_dev; 673 pcup->pco32.pc_sel.pc_func = pcp->pc_sel.pc_func; 674 pcup->pco32.pc_hdr = pcp->pc_hdr; 675 pcup->pco32.pc_subvendor = pcp->pc_subvendor; 676 pcup->pco32.pc_subdevice = pcp->pc_subdevice; 677 pcup->pco32.pc_vendor = pcp->pc_vendor; 678 pcup->pco32.pc_device = pcp->pc_device; 679 pcup->pco32.pc_class = pcp->pc_class; 680 pcup->pco32.pc_subclass = pcp->pc_subclass; 681 pcup->pco32.pc_progif = pcp->pc_progif; 682 pcup->pco32.pc_revid = pcp->pc_revid; 683 strlcpy(pcup->pco32.pd_name, pcp->pd_name, 684 sizeof(pcup->pco32.pd_name)); 685 pcup->pco32.pd_unit = (uint32_t)pcp->pd_unit; 686 return; 687 688 #endif /* COMPAT_FREEBSD32 */ 689 case PCIOCGETCONF_OLD: 690 pcup->pco.pc_sel.pc_bus = pcp->pc_sel.pc_bus; 691 pcup->pco.pc_sel.pc_dev = pcp->pc_sel.pc_dev; 692 pcup->pco.pc_sel.pc_func = pcp->pc_sel.pc_func; 693 pcup->pco.pc_hdr = pcp->pc_hdr; 694 pcup->pco.pc_subvendor = pcp->pc_subvendor; 695 pcup->pco.pc_subdevice = pcp->pc_subdevice; 696 pcup->pco.pc_vendor = pcp->pc_vendor; 697 pcup->pco.pc_device = pcp->pc_device; 698 pcup->pco.pc_class = pcp->pc_class; 699 pcup->pco.pc_subclass = pcp->pc_subclass; 700 pcup->pco.pc_progif = pcp->pc_progif; 701 pcup->pco.pc_revid = pcp->pc_revid; 702 strlcpy(pcup->pco.pd_name, pcp->pd_name, 703 sizeof(pcup->pco.pd_name)); 704 pcup->pco.pd_unit = pcp->pd_unit; 705 return; 706 #endif /* PRE7_COMPAT */ 707 708 default: 709 /* programmer error */ 710 return; 711 } 712 } 713 714 static int 715 pci_bar_mmap(device_t pcidev, struct pci_bar_mmap *pbm) 716 { 717 vm_map_t map; 718 vm_object_t obj; 719 struct thread *td; 720 struct sglist *sg; 721 struct pci_map *pm; 722 vm_paddr_t pbase; 723 vm_size_t plen; 724 vm_offset_t addr; 725 vm_prot_t prot; 726 int error, flags; 727 728 td = curthread; 729 map = &td->td_proc->p_vmspace->vm_map; 730 if ((pbm->pbm_flags & ~(PCIIO_BAR_MMAP_FIXED | PCIIO_BAR_MMAP_EXCL | 731 PCIIO_BAR_MMAP_RW | PCIIO_BAR_MMAP_ACTIVATE)) != 0 || 732 pbm->pbm_memattr != (vm_memattr_t)pbm->pbm_memattr || 733 !pmap_is_valid_memattr(map->pmap, pbm->pbm_memattr)) 734 return (EINVAL); 735 736 /* Fetch the BAR physical base and length. */ 737 pm = pci_find_bar(pcidev, pbm->pbm_reg); 738 if (pm == NULL) 739 return (EINVAL); 740 if (!pci_bar_enabled(pcidev, pm)) 741 return (EBUSY); /* XXXKIB enable if _ACTIVATE */ 742 if (!PCI_BAR_MEM(pm->pm_value)) 743 return (EIO); 744 pbase = trunc_page(pm->pm_value); 745 plen = round_page(pm->pm_value + ((pci_addr_t)1 << pm->pm_size)) - 746 pbase; 747 prot = VM_PROT_READ | (((pbm->pbm_flags & PCIIO_BAR_MMAP_RW) != 0) ? 748 VM_PROT_WRITE : 0); 749 750 /* Create vm structures and mmap. */ 751 sg = sglist_alloc(1, M_WAITOK); 752 error = sglist_append_phys(sg, pbase, plen); 753 if (error != 0) 754 goto out; 755 obj = vm_pager_allocate(OBJT_SG, sg, plen, prot, 0, td->td_ucred); 756 if (obj == NULL) { 757 error = EIO; 758 goto out; 759 } 760 obj->memattr = pbm->pbm_memattr; 761 flags = MAP_SHARED; 762 addr = 0; 763 if ((pbm->pbm_flags & PCIIO_BAR_MMAP_FIXED) != 0) { 764 addr = (uintptr_t)pbm->pbm_map_base; 765 flags |= MAP_FIXED; 766 } 767 if ((pbm->pbm_flags & PCIIO_BAR_MMAP_EXCL) != 0) 768 flags |= MAP_CHECK_EXCL; 769 error = vm_mmap_object(map, &addr, plen, prot, prot, flags, obj, 0, 770 FALSE, td); 771 if (error != 0) { 772 vm_object_deallocate(obj); 773 goto out; 774 } 775 pbm->pbm_map_base = (void *)addr; 776 pbm->pbm_map_length = plen; 777 pbm->pbm_bar_off = pm->pm_value - pbase; 778 pbm->pbm_bar_length = (pci_addr_t)1 << pm->pm_size; 779 780 out: 781 sglist_free(sg); 782 return (error); 783 } 784 785 static int 786 pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td) 787 { 788 device_t pcidev; 789 const char *name; 790 struct devlist *devlist_head; 791 struct pci_conf_io *cio = NULL; 792 struct pci_devinfo *dinfo; 793 struct pci_io *io; 794 struct pci_bar_io *bio; 795 struct pci_list_vpd_io *lvio; 796 struct pci_match_conf *pattern_buf; 797 struct pci_map *pm; 798 struct pci_bar_mmap *pbm; 799 size_t confsz, iolen; 800 int error, ionum, i, num_patterns; 801 union pci_conf_union pcu; 802 #ifdef PRE7_COMPAT 803 struct pci_io iodata; 804 struct pci_io_old *io_old; 805 806 io_old = NULL; 807 #endif 808 809 if (!(flag & FWRITE)) { 810 switch (cmd) { 811 case PCIOCGETCONF: 812 #ifdef PRE7_COMPAT 813 case PCIOCGETCONF_OLD: 814 #ifdef COMPAT_FREEBSD32 815 case PCIOCGETCONF_OLD32: 816 #endif 817 #endif 818 case PCIOCGETBAR: 819 case PCIOCLISTVPD: 820 break; 821 default: 822 return (EPERM); 823 } 824 } 825 826 827 switch (cmd) { 828 case PCIOCGETCONF: 829 #ifdef PRE7_COMPAT 830 case PCIOCGETCONF_OLD: 831 #ifdef COMPAT_FREEBSD32 832 case PCIOCGETCONF_OLD32: 833 #endif 834 #endif 835 cio = malloc(sizeof(struct pci_conf_io), M_TEMP, 836 M_WAITOK | M_ZERO); 837 pci_conf_io_init(cio, data, cmd); 838 pattern_buf = NULL; 839 num_patterns = 0; 840 dinfo = NULL; 841 842 cio->num_matches = 0; 843 844 /* 845 * If the user specified an offset into the device list, 846 * but the list has changed since they last called this 847 * ioctl, tell them that the list has changed. They will 848 * have to get the list from the beginning. 849 */ 850 if ((cio->offset != 0) 851 && (cio->generation != pci_generation)){ 852 cio->status = PCI_GETCONF_LIST_CHANGED; 853 error = 0; 854 goto getconfexit; 855 } 856 857 /* 858 * Check to see whether the user has asked for an offset 859 * past the end of our list. 860 */ 861 if (cio->offset >= pci_numdevs) { 862 cio->status = PCI_GETCONF_LAST_DEVICE; 863 error = 0; 864 goto getconfexit; 865 } 866 867 /* get the head of the device queue */ 868 devlist_head = &pci_devq; 869 870 /* 871 * Determine how much room we have for pci_conf structures. 872 * Round the user's buffer size down to the nearest 873 * multiple of sizeof(struct pci_conf) in case the user 874 * didn't specify a multiple of that size. 875 */ 876 confsz = pci_conf_size(cmd); 877 iolen = min(cio->match_buf_len - (cio->match_buf_len % confsz), 878 pci_numdevs * confsz); 879 880 /* 881 * Since we know that iolen is a multiple of the size of 882 * the pciconf union, it's okay to do this. 883 */ 884 ionum = iolen / confsz; 885 886 /* 887 * If this test is true, the user wants the pci_conf 888 * structures returned to match the supplied entries. 889 */ 890 if ((cio->num_patterns > 0) && (cio->num_patterns < pci_numdevs) 891 && (cio->pat_buf_len > 0)) { 892 /* 893 * pat_buf_len needs to be: 894 * num_patterns * sizeof(struct pci_match_conf) 895 * While it is certainly possible the user just 896 * allocated a large buffer, but set the number of 897 * matches correctly, it is far more likely that 898 * their kernel doesn't match the userland utility 899 * they're using. It's also possible that the user 900 * forgot to initialize some variables. Yes, this 901 * may be overly picky, but I hazard to guess that 902 * it's far more likely to just catch folks that 903 * updated their kernel but not their userland. 904 */ 905 if (cio->num_patterns * pci_match_conf_size(cmd) != 906 cio->pat_buf_len) { 907 /* The user made a mistake, return an error. */ 908 cio->status = PCI_GETCONF_ERROR; 909 error = EINVAL; 910 goto getconfexit; 911 } 912 913 /* 914 * Allocate a buffer to hold the patterns. 915 */ 916 pattern_buf = malloc(cio->pat_buf_len, M_TEMP, 917 M_WAITOK); 918 error = copyin(cio->patterns, pattern_buf, 919 cio->pat_buf_len); 920 if (error != 0) { 921 error = EINVAL; 922 goto getconfexit; 923 } 924 num_patterns = cio->num_patterns; 925 } else if ((cio->num_patterns > 0) 926 || (cio->pat_buf_len > 0)) { 927 /* 928 * The user made a mistake, spit out an error. 929 */ 930 cio->status = PCI_GETCONF_ERROR; 931 error = EINVAL; 932 goto getconfexit; 933 } 934 935 /* 936 * Go through the list of devices and copy out the devices 937 * that match the user's criteria. 938 */ 939 for (cio->num_matches = 0, i = 0, 940 dinfo = STAILQ_FIRST(devlist_head); 941 dinfo != NULL; 942 dinfo = STAILQ_NEXT(dinfo, pci_links), i++) { 943 944 if (i < cio->offset) 945 continue; 946 947 /* Populate pd_name and pd_unit */ 948 name = NULL; 949 if (dinfo->cfg.dev) 950 name = device_get_name(dinfo->cfg.dev); 951 if (name) { 952 strncpy(dinfo->conf.pd_name, name, 953 sizeof(dinfo->conf.pd_name)); 954 dinfo->conf.pd_name[PCI_MAXNAMELEN] = 0; 955 dinfo->conf.pd_unit = 956 device_get_unit(dinfo->cfg.dev); 957 } else { 958 dinfo->conf.pd_name[0] = '\0'; 959 dinfo->conf.pd_unit = 0; 960 } 961 962 if (pattern_buf == NULL || 963 pci_conf_match(cmd, pattern_buf, num_patterns, 964 &dinfo->conf) == 0) { 965 /* 966 * If we've filled up the user's buffer, 967 * break out at this point. Since we've 968 * got a match here, we'll pick right back 969 * up at the matching entry. We can also 970 * tell the user that there are more matches 971 * left. 972 */ 973 if (cio->num_matches >= ionum) { 974 error = 0; 975 break; 976 } 977 978 pci_conf_for_copyout(&dinfo->conf, &pcu, cmd); 979 error = copyout(&pcu, 980 (caddr_t)cio->matches + 981 confsz * cio->num_matches, confsz); 982 if (error) 983 break; 984 cio->num_matches++; 985 } 986 } 987 988 /* 989 * Set the pointer into the list, so if the user is getting 990 * n records at a time, where n < pci_numdevs, 991 */ 992 cio->offset = i; 993 994 /* 995 * Set the generation, the user will need this if they make 996 * another ioctl call with offset != 0. 997 */ 998 cio->generation = pci_generation; 999 1000 /* 1001 * If this is the last device, inform the user so he won't 1002 * bother asking for more devices. If dinfo isn't NULL, we 1003 * know that there are more matches in the list because of 1004 * the way the traversal is done. 1005 */ 1006 if (dinfo == NULL) 1007 cio->status = PCI_GETCONF_LAST_DEVICE; 1008 else 1009 cio->status = PCI_GETCONF_MORE_DEVS; 1010 1011 getconfexit: 1012 pci_conf_io_update_data(cio, data, cmd); 1013 free(cio, M_TEMP); 1014 free(pattern_buf, M_TEMP); 1015 1016 break; 1017 1018 #ifdef PRE7_COMPAT 1019 case PCIOCREAD_OLD: 1020 case PCIOCWRITE_OLD: 1021 io_old = (struct pci_io_old *)data; 1022 iodata.pi_sel.pc_domain = 0; 1023 iodata.pi_sel.pc_bus = io_old->pi_sel.pc_bus; 1024 iodata.pi_sel.pc_dev = io_old->pi_sel.pc_dev; 1025 iodata.pi_sel.pc_func = io_old->pi_sel.pc_func; 1026 iodata.pi_reg = io_old->pi_reg; 1027 iodata.pi_width = io_old->pi_width; 1028 iodata.pi_data = io_old->pi_data; 1029 data = (caddr_t)&iodata; 1030 /* FALLTHROUGH */ 1031 #endif 1032 case PCIOCREAD: 1033 case PCIOCWRITE: 1034 io = (struct pci_io *)data; 1035 switch(io->pi_width) { 1036 case 4: 1037 case 2: 1038 case 1: 1039 /* Make sure register is not negative and aligned. */ 1040 if (io->pi_reg < 0 || 1041 io->pi_reg & (io->pi_width - 1)) { 1042 error = EINVAL; 1043 break; 1044 } 1045 /* 1046 * Assume that the user-level bus number is 1047 * in fact the physical PCI bus number. 1048 * Look up the grandparent, i.e. the bridge device, 1049 * so that we can issue configuration space cycles. 1050 */ 1051 pcidev = pci_find_dbsf(io->pi_sel.pc_domain, 1052 io->pi_sel.pc_bus, io->pi_sel.pc_dev, 1053 io->pi_sel.pc_func); 1054 if (pcidev) { 1055 #ifdef PRE7_COMPAT 1056 if (cmd == PCIOCWRITE || cmd == PCIOCWRITE_OLD) 1057 #else 1058 if (cmd == PCIOCWRITE) 1059 #endif 1060 pci_write_config(pcidev, 1061 io->pi_reg, 1062 io->pi_data, 1063 io->pi_width); 1064 #ifdef PRE7_COMPAT 1065 else if (cmd == PCIOCREAD_OLD) 1066 io_old->pi_data = 1067 pci_read_config(pcidev, 1068 io->pi_reg, 1069 io->pi_width); 1070 #endif 1071 else 1072 io->pi_data = 1073 pci_read_config(pcidev, 1074 io->pi_reg, 1075 io->pi_width); 1076 error = 0; 1077 } else { 1078 #ifdef COMPAT_FREEBSD4 1079 if (cmd == PCIOCREAD_OLD) { 1080 io_old->pi_data = -1; 1081 error = 0; 1082 } else 1083 #endif 1084 error = ENODEV; 1085 } 1086 break; 1087 default: 1088 error = EINVAL; 1089 break; 1090 } 1091 break; 1092 1093 case PCIOCGETBAR: 1094 bio = (struct pci_bar_io *)data; 1095 1096 /* 1097 * Assume that the user-level bus number is 1098 * in fact the physical PCI bus number. 1099 */ 1100 pcidev = pci_find_dbsf(bio->pbi_sel.pc_domain, 1101 bio->pbi_sel.pc_bus, bio->pbi_sel.pc_dev, 1102 bio->pbi_sel.pc_func); 1103 if (pcidev == NULL) { 1104 error = ENODEV; 1105 break; 1106 } 1107 pm = pci_find_bar(pcidev, bio->pbi_reg); 1108 if (pm == NULL) { 1109 error = EINVAL; 1110 break; 1111 } 1112 bio->pbi_base = pm->pm_value; 1113 bio->pbi_length = (pci_addr_t)1 << pm->pm_size; 1114 bio->pbi_enabled = pci_bar_enabled(pcidev, pm); 1115 error = 0; 1116 break; 1117 case PCIOCATTACHED: 1118 error = 0; 1119 io = (struct pci_io *)data; 1120 pcidev = pci_find_dbsf(io->pi_sel.pc_domain, io->pi_sel.pc_bus, 1121 io->pi_sel.pc_dev, io->pi_sel.pc_func); 1122 if (pcidev != NULL) 1123 io->pi_data = device_is_attached(pcidev); 1124 else 1125 error = ENODEV; 1126 break; 1127 case PCIOCLISTVPD: 1128 lvio = (struct pci_list_vpd_io *)data; 1129 1130 /* 1131 * Assume that the user-level bus number is 1132 * in fact the physical PCI bus number. 1133 */ 1134 pcidev = pci_find_dbsf(lvio->plvi_sel.pc_domain, 1135 lvio->plvi_sel.pc_bus, lvio->plvi_sel.pc_dev, 1136 lvio->plvi_sel.pc_func); 1137 if (pcidev == NULL) { 1138 error = ENODEV; 1139 break; 1140 } 1141 error = pci_list_vpd(pcidev, lvio); 1142 break; 1143 1144 case PCIOCBARMMAP: 1145 pbm = (struct pci_bar_mmap *)data; 1146 if ((flag & FWRITE) == 0 && 1147 (pbm->pbm_flags & PCIIO_BAR_MMAP_RW) != 0) 1148 return (EPERM); 1149 pcidev = pci_find_dbsf(pbm->pbm_sel.pc_domain, 1150 pbm->pbm_sel.pc_bus, pbm->pbm_sel.pc_dev, 1151 pbm->pbm_sel.pc_func); 1152 error = pcidev == NULL ? ENODEV : pci_bar_mmap(pcidev, pbm); 1153 break; 1154 1155 default: 1156 error = ENOTTY; 1157 break; 1158 } 1159 1160 return (error); 1161 } 1162