25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: bus_pci.c,v 1.65 2006/05/10 03:32:32 debug Exp $ |
* $Id: bus_pci.c,v 1.70 2006/08/12 19:38:24 debug Exp $ |
29 |
* |
* |
30 |
* Generic PCI bus framework. This is not a normal "device", but is used by |
* Generic PCI bus framework. This is not a normal "device", but is used by |
31 |
* individual PCI controllers and devices. |
* individual PCI controllers and devices. |
57 |
#include "memory.h" |
#include "memory.h" |
58 |
#include "misc.h" |
#include "misc.h" |
59 |
|
|
60 |
|
#include "wdc.h" |
61 |
|
|
62 |
extern int verbose; |
extern int verbose; |
63 |
|
|
64 |
|
|
149 |
pci_data->last_was_write_ffffffff = 1; |
pci_data->last_was_write_ffffffff = 1; |
150 |
return; |
return; |
151 |
} |
} |
152 |
/* Writes are not really supported yet: */ |
|
153 |
if (idata != x) { |
if (dev->cfg_reg_write != NULL) { |
154 |
|
dev->cfg_reg_write(dev, pci_data->cur_reg, *data); |
155 |
|
} else { |
156 |
|
/* Print a warning for unhandled writes: */ |
157 |
debug("[ bus_pci: write to PCI DATA: data = 0x%08llx" |
debug("[ bus_pci: write to PCI DATA: data = 0x%08llx" |
158 |
" differs from current value 0x%08llx; NOT YET" |
" (current value = 0x%08llx); NOT YET" |
159 |
" SUPPORTED. bus %i, device %i, function %i (%s)" |
" SUPPORTED. bus %i, device %i, function %i (%s)" |
160 |
" register 0x%02x ]\n", (long long)idata, |
" register 0x%02x ]\n", (long long)idata, |
161 |
(long long)x, pci_data->cur_bus, |
(long long)x, pci_data->cur_bus, |
162 |
pci_data->cur_device, pci_data->cur_func, |
pci_data->cur_device, pci_data->cur_func, |
163 |
dev->name, pci_data->cur_reg); |
dev->name, pci_data->cur_reg); |
164 |
|
|
165 |
|
/* Special warning, to detect if NetBSD's special |
166 |
|
detection of PCI devices fails: */ |
167 |
|
if (pci_data->cur_reg == PCI_COMMAND_STATUS_REG |
168 |
|
&& !((*data) & PCI_COMMAND_IO_ENABLE)) { |
169 |
|
fatal("\n[ NetBSD PCI detection stuff not" |
170 |
|
" yet implemented for device '%s' ]\n", |
171 |
|
dev->name); |
172 |
|
} |
173 |
} |
} |
174 |
return; |
return; |
175 |
} |
} |
434 |
|
|
435 |
|
|
436 |
/* |
/* |
437 |
* Integraphics Systems "igsfb" Framebuffer (graphics) card. |
* Integraphics Systems "igsfb" Framebuffer (graphics) card, used in at |
438 |
* |
* least the NetWinder. |
|
* TODO |
|
439 |
*/ |
*/ |
440 |
|
|
441 |
#define PCI_VENDOR_INTEGRAPHICS 0x10ea |
#define PCI_VENDOR_INTEGRAPHICS 0x10ea |
442 |
|
|
443 |
PCIINIT(igsfb) |
PCIINIT(igsfb) |
444 |
{ |
{ |
445 |
|
char tmpstr[200]; |
446 |
|
|
447 |
PCI_SET_DATA(PCI_ID_REG, |
PCI_SET_DATA(PCI_ID_REG, |
448 |
PCI_ID_CODE(PCI_VENDOR_INTEGRAPHICS, 0x2010)); |
PCI_ID_CODE(PCI_VENDOR_INTEGRAPHICS, 0x2010)); |
449 |
|
|
454 |
/* TODO */ |
/* TODO */ |
455 |
PCI_SET_DATA(0x10, 0x08000000); |
PCI_SET_DATA(0x10, 0x08000000); |
456 |
|
|
457 |
dev_vga_init(machine, mem, pd->pcibus->isa_membase + 0xa0000, |
snprintf(tmpstr, sizeof(tmpstr), "igsfb addr=0x%llx", |
458 |
0x88800000 + 0x3c0, machine->machine_name); |
(long long)(pd->pcibus->isa_membase + 0x08000000)); |
459 |
|
device_add(machine, tmpstr); |
460 |
} |
} |
461 |
|
|
462 |
|
|
643 |
|
|
644 |
|
|
645 |
/* |
/* |
646 |
|
* AMD PCnet Ethernet card. |
647 |
|
* |
648 |
|
* "Am79c970A PCnet-PCI II rev 0" or similar. |
649 |
|
*/ |
650 |
|
|
651 |
|
#define PCI_VENDOR_AMD 0x1022 /* Advanced Micro Devices */ |
652 |
|
#define PCI_PRODUCT_AMD_PCNET_PCI 0x2000 /* PCnet-PCI Ethernet */ |
653 |
|
|
654 |
|
PCIINIT(pcn) |
655 |
|
{ |
656 |
|
int irq; |
657 |
|
|
658 |
|
PCI_SET_DATA(PCI_ID_REG, PCI_ID_CODE(PCI_VENDOR_AMD, |
659 |
|
PCI_PRODUCT_AMD_PCNET_PCI)); |
660 |
|
|
661 |
|
PCI_SET_DATA(PCI_CLASS_REG, PCI_CLASS_CODE(PCI_CLASS_NETWORK, |
662 |
|
PCI_SUBCLASS_NETWORK_ETHERNET, 0) + 0x00); /* Revision 0 */ |
663 |
|
|
664 |
|
switch (machine->machine_type) { |
665 |
|
|
666 |
|
case MACHINE_EVBMIPS: |
667 |
|
irq = (1 << 8) + 10; /* TODO */ |
668 |
|
break; |
669 |
|
|
670 |
|
default:fatal("pcn in non-implemented machine type %i\n", |
671 |
|
machine->machine_type); |
672 |
|
exit(1); |
673 |
|
} |
674 |
|
|
675 |
|
PCI_SET_DATA(PCI_INTERRUPT_REG, 0x01100000 | irq); |
676 |
|
|
677 |
|
/* |
678 |
|
* TODO: Add the pcn device here. The pcn device will need to work as |
679 |
|
* a wrapper for dev_le + all the DMA magic and whatever is required. |
680 |
|
* It's too much to implement right now. |
681 |
|
*/ |
682 |
|
} |
683 |
|
|
684 |
|
|
685 |
|
|
686 |
|
/* |
687 |
* Intel 31244 Serial ATA Controller |
* Intel 31244 Serial ATA Controller |
688 |
* Intel 82371SB PIIX3 PCI-ISA bridge |
* Intel 82371SB PIIX3 PCI-ISA bridge |
689 |
* Intel 82371AB PIIX4 PCI-ISA bridge |
* Intel 82371AB PIIX4 PCI-ISA bridge |
778 |
PCI_SET_DATA(0x60, 0x0f0e0b0a); |
PCI_SET_DATA(0x60, 0x0f0e0b0a); |
779 |
} |
} |
780 |
|
|
781 |
|
struct piix_ide_extra { |
782 |
|
void *wdc0; |
783 |
|
void *wdc1; |
784 |
|
}; |
785 |
|
|
786 |
|
int piix_ide_cfg_reg_write(struct pci_device *pd, int reg, uint32_t value) |
787 |
|
{ |
788 |
|
void *wdc0 = ((struct piix_ide_extra *)pd->extra)->wdc0; |
789 |
|
void *wdc1 = ((struct piix_ide_extra *)pd->extra)->wdc1; |
790 |
|
int enabled = 0; |
791 |
|
|
792 |
|
switch (reg) { |
793 |
|
case PCI_COMMAND_STATUS_REG: |
794 |
|
if (value & PCI_COMMAND_IO_ENABLE) |
795 |
|
enabled = 1; |
796 |
|
if (wdc0 != NULL) |
797 |
|
wdc_set_io_enabled(wdc0, enabled); |
798 |
|
if (wdc1 != NULL) |
799 |
|
wdc_set_io_enabled(wdc1, enabled); |
800 |
|
return 1; |
801 |
|
} |
802 |
|
|
803 |
|
return 0; |
804 |
|
} |
805 |
|
|
806 |
PCIINIT(piix3_ide) |
PCIINIT(piix3_ide) |
807 |
{ |
{ |
808 |
char tmpstr[100]; |
char tmpstr[100]; |
818 |
/* channel 0 and 1 enabled as IDE */ |
/* channel 0 and 1 enabled as IDE */ |
819 |
PCI_SET_DATA(0x40, 0x80008000); |
PCI_SET_DATA(0x40, 0x80008000); |
820 |
|
|
821 |
|
pd->extra = malloc(sizeof(struct piix_ide_extra)); |
822 |
|
if (pd->extra == NULL) { |
823 |
|
fatal("Out of memory.\n"); |
824 |
|
exit(1); |
825 |
|
} |
826 |
|
((struct piix_ide_extra *)pd->extra)->wdc0 = NULL; |
827 |
|
((struct piix_ide_extra *)pd->extra)->wdc1 = NULL; |
828 |
|
|
829 |
if (diskimage_exist(machine, 0, DISKIMAGE_IDE) || |
if (diskimage_exist(machine, 0, DISKIMAGE_IDE) || |
830 |
diskimage_exist(machine, 1, DISKIMAGE_IDE)) { |
diskimage_exist(machine, 1, DISKIMAGE_IDE)) { |
831 |
snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i", |
snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i", |
832 |
(long long)(pd->pcibus->isa_portbase + 0x1f0), |
(long long)(pd->pcibus->isa_portbase + 0x1f0), |
833 |
pd->pcibus->isa_irqbase + 14); |
pd->pcibus->isa_irqbase + 14); |
834 |
device_add(machine, tmpstr); |
((struct piix_ide_extra *)pd->extra)->wdc0 = |
835 |
|
device_add(machine, tmpstr); |
836 |
} |
} |
837 |
|
|
838 |
if (diskimage_exist(machine, 2, DISKIMAGE_IDE) || |
if (diskimage_exist(machine, 2, DISKIMAGE_IDE) || |
840 |
snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i", |
snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i", |
841 |
(long long)(pd->pcibus->isa_portbase + 0x170), |
(long long)(pd->pcibus->isa_portbase + 0x170), |
842 |
pd->pcibus->isa_irqbase + 15); |
pd->pcibus->isa_irqbase + 15); |
843 |
device_add(machine, tmpstr); |
((struct piix_ide_extra *)pd->extra)->wdc1 = |
844 |
|
device_add(machine, tmpstr); |
845 |
} |
} |
846 |
|
|
847 |
|
pd->cfg_reg_write = piix_ide_cfg_reg_write; |
848 |
} |
} |
849 |
|
|
850 |
PCIINIT(piix4_ide) |
PCIINIT(piix4_ide) |
862 |
/* channel 0 and 1 enabled as IDE */ |
/* channel 0 and 1 enabled as IDE */ |
863 |
PCI_SET_DATA(0x40, 0x80008000); |
PCI_SET_DATA(0x40, 0x80008000); |
864 |
|
|
865 |
|
pd->extra = malloc(sizeof(struct piix_ide_extra)); |
866 |
|
if (pd->extra == NULL) { |
867 |
|
fatal("Out of memory.\n"); |
868 |
|
exit(1); |
869 |
|
} |
870 |
|
((struct piix_ide_extra *)pd->extra)->wdc0 = NULL; |
871 |
|
((struct piix_ide_extra *)pd->extra)->wdc1 = NULL; |
872 |
|
|
873 |
if (diskimage_exist(machine, 0, DISKIMAGE_IDE) || |
if (diskimage_exist(machine, 0, DISKIMAGE_IDE) || |
874 |
diskimage_exist(machine, 1, DISKIMAGE_IDE)) { |
diskimage_exist(machine, 1, DISKIMAGE_IDE)) { |
875 |
snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i", |
snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i", |
876 |
(long long)(pd->pcibus->isa_portbase + 0x1f0), |
(long long)(pd->pcibus->isa_portbase + 0x1f0), |
877 |
pd->pcibus->isa_irqbase + 14); |
pd->pcibus->isa_irqbase + 14); |
878 |
device_add(machine, tmpstr); |
((struct piix_ide_extra *)pd->extra)->wdc0 = |
879 |
|
device_add(machine, tmpstr); |
880 |
} |
} |
881 |
|
|
882 |
if (diskimage_exist(machine, 2, DISKIMAGE_IDE) || |
if (diskimage_exist(machine, 2, DISKIMAGE_IDE) || |
884 |
snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i", |
snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i", |
885 |
(long long)(pd->pcibus->isa_portbase + 0x170), |
(long long)(pd->pcibus->isa_portbase + 0x170), |
886 |
pd->pcibus->isa_irqbase + 15); |
pd->pcibus->isa_irqbase + 15); |
887 |
device_add(machine, tmpstr); |
((struct piix_ide_extra *)pd->extra)->wdc1 = |
888 |
|
device_add(machine, tmpstr); |
889 |
} |
} |
890 |
|
|
891 |
|
pd->cfg_reg_write = piix_ide_cfg_reg_write; |
892 |
} |
} |
893 |
|
|
894 |
|
|
962 |
PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0)); |
PCI_BHLC_CODE(0,0, 1 /* multi-function */, 0x40,0)); |
963 |
} |
} |
964 |
|
|
965 |
|
struct vt82c586_ide_extra { |
966 |
|
void *wdc0; |
967 |
|
void *wdc1; |
968 |
|
}; |
969 |
|
|
970 |
|
int vt82c586_ide_cfg_reg_write(struct pci_device *pd, int reg, uint32_t value) |
971 |
|
{ |
972 |
|
void *wdc0 = ((struct vt82c586_ide_extra *)pd->extra)->wdc0; |
973 |
|
void *wdc1 = ((struct vt82c586_ide_extra *)pd->extra)->wdc1; |
974 |
|
int enabled = 0; |
975 |
|
|
976 |
|
switch (reg) { |
977 |
|
case PCI_COMMAND_STATUS_REG: |
978 |
|
if (value & PCI_COMMAND_IO_ENABLE) |
979 |
|
enabled = 1; |
980 |
|
if (wdc0 != NULL) |
981 |
|
wdc_set_io_enabled(wdc0, enabled); |
982 |
|
if (wdc1 != NULL) |
983 |
|
wdc_set_io_enabled(wdc1, enabled); |
984 |
|
return 1; |
985 |
|
} |
986 |
|
|
987 |
|
return 0; |
988 |
|
} |
989 |
|
|
990 |
PCIINIT(vt82c586_ide) |
PCIINIT(vt82c586_ide) |
991 |
{ |
{ |
992 |
char tmpstr[100]; |
char tmpstr[100]; |
1002 |
/* channel 0 and 1 enabled */ |
/* channel 0 and 1 enabled */ |
1003 |
PCI_SET_DATA(0x40, 0x00000003); |
PCI_SET_DATA(0x40, 0x00000003); |
1004 |
|
|
1005 |
|
pd->extra = malloc(sizeof(struct vt82c586_ide_extra)); |
1006 |
|
if (pd->extra == NULL) { |
1007 |
|
fatal("Out of memory.\n"); |
1008 |
|
exit(1); |
1009 |
|
} |
1010 |
|
((struct vt82c586_ide_extra *)pd->extra)->wdc0 = NULL; |
1011 |
|
((struct vt82c586_ide_extra *)pd->extra)->wdc1 = NULL; |
1012 |
|
|
1013 |
if (diskimage_exist(machine, 0, DISKIMAGE_IDE) || |
if (diskimage_exist(machine, 0, DISKIMAGE_IDE) || |
1014 |
diskimage_exist(machine, 1, DISKIMAGE_IDE)) { |
diskimage_exist(machine, 1, DISKIMAGE_IDE)) { |
1015 |
snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i", |
snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i", |
1016 |
(long long)(pd->pcibus->isa_portbase + 0x1f0), |
(long long)(pd->pcibus->isa_portbase + 0x1f0), |
1017 |
pd->pcibus->isa_irqbase + 14); |
pd->pcibus->isa_irqbase + 14); |
1018 |
device_add(machine, tmpstr); |
((struct vt82c586_ide_extra *)pd->extra)->wdc0 = |
1019 |
|
device_add(machine, tmpstr); |
1020 |
} |
} |
1021 |
|
|
1022 |
if (diskimage_exist(machine, 2, DISKIMAGE_IDE) || |
if (diskimage_exist(machine, 2, DISKIMAGE_IDE) || |
1024 |
snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i", |
snprintf(tmpstr, sizeof(tmpstr), "wdc addr=0x%llx irq=%i", |
1025 |
(long long)(pd->pcibus->isa_portbase + 0x170), |
(long long)(pd->pcibus->isa_portbase + 0x170), |
1026 |
pd->pcibus->isa_irqbase + 15); |
pd->pcibus->isa_irqbase + 15); |
1027 |
device_add(machine, tmpstr); |
((struct vt82c586_ide_extra *)pd->extra)->wdc1 = |
1028 |
|
device_add(machine, tmpstr); |
1029 |
} |
} |
1030 |
|
|
1031 |
|
pd->cfg_reg_write = vt82c586_ide_cfg_reg_write; |
1032 |
} |
} |
1033 |
|
|
1034 |
|
|