Rev 951 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 951 | Rev 953 | ||
---|---|---|---|
Line 47... | Line 47... | ||
47 | }; |
47 | }; |
48 | 48 | ||
Line 49... | Line 49... | ||
49 | 49 | ||
- | 50 | #include "pci.inc" |
|
Line 50... | Line 51... | ||
50 | #include "pci.inc" |
51 | #include "isoch.inc" |
51 | 52 | ||
52 | static void intel_8xx_tlbflush(void *mem) |
53 | static void intel_8xx_tlbflush(void *mem) |
Line 497... | Line 498... | ||
497 | } |
498 | } |
498 | } |
499 | } |
499 | 500 | ||
Line 500... | Line -... | ||
500 | - | ||
501 | struct agp_3_5_dev |
- | |
502 | { |
- | |
503 | link_t link; |
- | |
504 | int capndx; |
- | |
505 | u32_t maxbw; |
- | |
506 | PCITAG tag; |
- | |
507 | }; |
- | |
508 | - | ||
509 | - | ||
510 | /* |
- | |
511 | * Fully configure and enable an AGP 3.0 host bridge and all the devices |
- | |
512 | * lying behind it. |
- | |
513 | */ |
- | |
514 | int agp_3_5_enable(agp_t *bridge) |
- | |
515 | { |
- | |
516 | u8_t mcapndx; |
- | |
517 | u32_t isoch, arqsz; |
- | |
518 | u32_t tstatus, mstatus, ncapid; |
- | |
519 | u32_t mmajor; |
- | |
520 | u16_t mpstat; |
- | |
521 | - | ||
522 | link_t dev_list; |
- | |
523 | - | ||
524 | struct agp_3_5_dev *cur, *pos; |
- | |
525 | - | ||
526 | unsigned int ndevs = 0; |
- | |
527 | PCITAG dev = 0; |
- | |
528 | int ret = 0; |
- | |
529 | - | ||
530 | /* Extract some power-on defaults from the target */ |
- | |
531 | tstatus = pciReadLong(bridge->PciTag, bridge->capndx+AGPSTAT); |
- | |
532 | isoch = (tstatus >> 17) & 0x1; |
- | |
533 | if (isoch == 0) /* isoch xfers not available, bail out. */ |
- | |
534 | return -1; |
- | |
535 | - | ||
536 | arqsz = (tstatus >> 13) & 0x7; |
- | |
537 | - | ||
538 | list_initialize(&dev_list); |
- | |
539 | - | ||
540 | /* Find all AGP devices, and add them to dev_list. */ |
- | |
541 | for_each_pci_dev(dev) |
- | |
542 | { |
- | |
543 | u16_t devclass; |
- | |
544 | - | ||
545 | mcapndx = pci_find_capability(dev, PCI_CAP_ID_AGP); |
- | |
546 | if (mcapndx == 0) |
- | |
547 | continue; |
- | |
548 | - | ||
549 | devclass = pciReadWord(dev, 0x0A); |
- | |
550 | - | ||
551 | switch (devclass & 0xff00) |
- | |
552 | { |
- | |
553 | case 0x0600: /* Bridge */ |
- | |
554 | /* Skip bridges. We should call this function for each one. */ |
- | |
555 | continue; |
- | |
556 | - | ||
557 | case 0x0001: /* Unclassified device */ |
- | |
558 | /* Don't know what this is, but log it for investigation. */ |
- | |
559 | if (mcapndx != 0) { |
- | |
560 | dbgprintf("Wacky, found unclassified AGP device.\n"); |
- | |
561 | } |
- | |
562 | continue; |
- | |
563 | - | ||
564 | case 0x0300: /* Display controller */ |
- | |
565 | case 0x0400: /* Multimedia controller */ |
- | |
566 | if((cur = malloc(sizeof(*cur))) == NULL) |
- | |
567 | { |
- | |
568 | ret = -1; |
- | |
569 | goto free_and_exit; |
- | |
570 | } |
- | |
571 | cur->tag = dev; |
- | |
572 | list_prepend(&cur->link, &dev_list); |
- | |
573 | ndevs++; |
- | |
574 | continue; |
- | |
575 | - | ||
576 | default: |
- | |
577 | continue; |
- | |
578 | } |
- | |
579 | } |
- | |
580 | - | ||
581 | /* |
- | |
582 | * Take an initial pass through the devices lying behind our host |
- | |
583 | * bridge. Make sure each one is actually an AGP 3.0 device, otherwise |
- | |
584 | * exit with an error message. Along the way store the AGP 3.0 |
- | |
585 | * cap_ptr for each device |
- | |
586 | */ |
- | |
587 | - | ||
588 | cur = (struct agp_3_5_dev*)dev_list.next; |
- | |
589 | - | ||
590 | while(&cur->link != &dev_list) |
- | |
591 | { |
- | |
592 | dev = cur->tag; |
- | |
593 | - | ||
594 | mpstat = pciReadWord(dev, PCI_STATUS); |
- | |
595 | if ((mpstat & PCI_STATUS_CAP_LIST) == 0) |
- | |
596 | continue; |
- | |
597 | - | ||
598 | mcapndx = pciReadByte(dev, PCI_CAPABILITY_LIST); |
- | |
599 | if (mcapndx != 0) { |
- | |
600 | do { |
- | |
601 | ncapid = pciReadLong(dev, mcapndx); |
- | |
602 | if ((ncapid & 0xff) != 2) |
- | |
603 | mcapndx = (ncapid >> 8) & 0xff; |
- | |
604 | } |
- | |
605 | while (((ncapid & 0xff) != 2) && (mcapndx != 0)); |
- | |
606 | } |
- | |
607 | - | ||
608 | if (mcapndx == 0) { |
- | |
609 | dbgprintf("woah! Non-AGP device " |
- | |
610 | "found on the secondary bus of an AGP 3.5 bridge!\n"); |
- | |
611 | ret = -1; |
- | |
612 | goto free_and_exit; |
- | |
613 | } |
- | |
614 | - | ||
615 | mmajor = (ncapid >> AGP_MAJOR_VERSION_SHIFT) & 0xf; |
- | |
616 | if (mmajor < 3) { |
- | |
617 | dbgprintf("woah! AGP 2.0 device " |
- | |
618 | "found on the secondary bus of an AGP 3.5 " |
- | |
619 | "bridge operating with AGP 3.0 electricals!\n"); |
- | |
620 | ret = -1; |
- | |
621 | goto free_and_exit; |
- | |
622 | } |
- | |
623 | - | ||
624 | cur->capndx = mcapndx; |
- | |
625 | - | ||
626 | mstatus = pciReadLong(dev, cur->capndx+AGPSTAT); |
- | |
627 | - | ||
628 | if (((mstatus >> 3) & 0x1) == 0) { |
- | |
629 | dbgprintf("woah! AGP 3.x device " |
- | |
630 | "not operating in AGP 3.x mode found on the " |
- | |
631 | "secondary bus of an AGP 3.5 bridge operating " |
- | |
632 | "with AGP 3.0 electricals!\n"); |
- | |
633 | ret = -1; |
- | |
634 | goto free_and_exit; |
- | |
635 | } |
- | |
636 | cur = (struct agp_3_5_dev*)cur->link.next; |
- | |
637 | } |
- | |
638 | - | ||
639 | /* |
- | |
640 | * Call functions to divide target resources amongst the AGP 3.0 |
- | |
641 | * masters. This process is dramatically different depending on |
- | |
642 | * whether isochronous transfers are supported. |
- | |
643 | */ |
- | |
644 | if (isoch) { |
- | |
645 | ret = agp_3_5_isochronous_node_enable(bridge, &dev_list, ndevs); |
- | |
646 | if (ret) { |
- | |
647 | dbgprintf("Something bad happened setting " |
- | |
648 | "up isochronous xfers. Falling back to " |
- | |
649 | "non-isochronous xfer mode.\n"); |
- | |
650 | } else { |
- | |
651 | goto free_and_exit; |
- | |
652 | } |
- | |
653 | } |
- | |
654 | agp_3_5_nonisochronous_node_enable(bridge, dev_list, ndevs); |
- | |
655 | - | ||
656 | free_and_exit: |
- | |
657 | /* Be sure to free the dev_list */ |
- | |
658 | for (pos = (struct agp_3_5_dev*)dev_list.next; &pos->link != &dev_list; ) |
- | |
659 | { |
- | |
660 | cur = pos; |
- | |
661 | - | ||
662 | pos = (struct agp_3_5_dev*)pos->link.next; |
- | |
663 | free(cur); |
- | |
664 | } |
- | |
665 | - | ||
666 | get_out: |
- | |
667 | return ret; |
- | |
Line 668... | Line 501... | ||
668 | } |
501 | |
669 | 502 | ||
670 | 503 |