int pci_MMIO_address_map(unsigned bus_device_func, unsigned reg, unsigned long mask) { DWORD addr; DWORD orig; pci_MMIO_register = reg; pci_MMIO_bus_device_func = bus_device_func; if (pci_read_dword(pci_MMIO_bus_device_func, pci_MMIO_register, &orig) != 0) return -1; if (!orig) { log_std(("pci: MMIO address null\n")); return -1; } log_std(("pci: MMIO orig %08lx\n", (unsigned long)orig)); addr = orig & (0xFFFFFFF0 & mask); log_std(("pci: MMIO addr %08lx\n", (unsigned long)addr)); pci_MMIO_physical_address = addr; pci_MMIO_physical_size = 0x10000; if (map_create_linear_mapping(&pci_MMIO_linear_address, pci_MMIO_physical_address, pci_MMIO_physical_size) != 0) { return -1; } if (map_create_selector(&pci_MMIO_selector, pci_MMIO_linear_address, pci_MMIO_physical_size) != 0) { map_remove_linear_mapping(pci_MMIO_physical_address, pci_MMIO_physical_size); return -1; } return 0; }
ULONG SavMob_CheckHW(void) { static USHORT SavMobList[13]={0x8c10, //Savage_MX_MV 0x8c11, //Savage_MX 0x8c12, //Savage_IX_MV 0x8c13, //Savage_IX 0x8c22, //SuperSavage_MX128 0x8c24, //SuperSavage_MX64 0x8c26, //SuperSavage_MX64C 0x8c2a, //SuperSavage_IX128SDR 0x8c2b, //SuperSavage_IX128DDR 0x8c2c, //SuperSavage_IX64SDR 0x8c2d, //SuperSavage_IX64DDR 0x8c2e, //SuperSavage_IXCSDR 0x8c2f //SuperSavage_IXCDDR }; ULONG i,rc,temp; rc=pci_read_dword(&PciDevice,0,&temp); if (rc) return RC_ERROR; temp>>=16; //temp=PCI DEVICE ID i=0; while ((temp!=SavMobList[i])&&(i<13)) i++; if (i==13) return RC_ERROR; pci_read_dword(&PciDevice,0x10,&temp); temp&=0xffffff00; if (i<4) temp+=0x1000000; MMIO=PhysToLin(temp,0x80000); if (!MMIO) return RC_ERROR; pRegs->ColorConvert1=0x0000c892; pRegs->ColorConvert2=0x00039f9a; pRegs->ColorConvert3=0x01f1547e; pRegs->brightness=128; pRegs->contrast=128; pRegs->saturation=128; pRegs->hue=128; HideVideo=SavMob_HideVideo; VideoCaps=SavMob_VideoCaps; SetVideoAttr=SavMob_SetVideoAttr; GetVideoAttr=SavMob_GetVideoAttr; DisplayVideo=SavMob_DisplayVideo; SetupVideo=SavMob_SetupVideo; RestoreVideo=SavMob_RestoreVideo; return RC_SUCCESS; }
uint32_t pci_device_get_memory_size(struct pci_address* addr, uint32_t bar_offset) { // Save the original BAR so we can restore it once we're done uint32_t orig_bar = pci_read_dword(addr, bar_offset); // Writing all 1s to the BAR register makes the device // write the size of the memory region it occupies into the BAR pci_write_dword(addr, bar_offset, 0xFFFFFFFF); // Read the size from the BAR uint32_t size = pci_read_dword(addr, bar_offset); // Reset the BAR to the original value pci_write_dword(addr, bar_offset, orig_bar); // The size is actually inversed, so NOT the entire thing, // ignoring bit 0 as it's only used to indicate whether the device // uses port I/O or is memory mapped return ~(size & ~1); }
ULONG MACH_CheckHW(void) { static USHORT MACHList[]={0x4754,0x4755,0x475a,0x4757, 0x4756,0x4742,0x4744,0x4749, 0x4750,0x4751,0x4c49,0x4c42, 0x4c50,0x4c47,0x474d,0x4c4d}; ULONG i,rc,temp; rc=pci_read_dword(&PciDevice,0,&temp); if (rc) return RC_ERROR; temp>>=16; //temp=PCI DEVICE ID i=0; while ((temp!=MACHList[i])&&(i<16)) i++; if (i==16) return RC_ERROR; rc=pci_read_dword(&PciDevice,0x10,&temp); if (rc) return RC_ERROR; temp&=0xfff00000;//mask out lower bits MMIO=PhysToLin(temp+0x7ff800,0x800); if (MMIO==NULL) return RC_ERROR; //enable block 1 access WaitForIdle(7); WRITEREG(MMIO,BUS_CNTL,READREG(MMIO,BUS_CNTL)|BUS_CNTL_MASK); WRITEREG(MMIO,SCALER_COLOUR_CNTL, (0x00) | (0x10 << 8) | (0x10 << 16) ); WRITEREG(MMIO,SCALER_H_COEFF0, (0x00) | (0x20 << 8) ); WRITEREG(MMIO,SCALER_H_COEFF1, (0x0D) | (0x20 << 8) | (0x06 << 16) | (0x0D << 24) ); WRITEREG(MMIO,SCALER_H_COEFF2, (0x0D) | (0x1C << 8) | (0x0A << 16) | (0x0D << 24) ); WRITEREG(MMIO,SCALER_H_COEFF3, (0x0C) | (0x1A << 8) | (0x0E << 16) | (0x0C << 24) ); WRITEREG(MMIO,SCALER_H_COEFF4, (0x0C) | (0x14 << 8) | (0x14 << 16) | (0x0C << 24) ); pRegs->scale_cntl=0x0c; //filtering on, red temp=6500K pRegs->chipflags|=MACH_NEED_RESETUP; HideVideo=MACH_HideVideo; VideoCaps=MACH_VideoCaps; SetVideoAttr=MACH_SetVideoAttr; GetVideoAttr=MACH_GetVideoAttr; DisplayVideo=MACH_DisplayVideo; SetupVideo=MACH_SetupVideo; RestoreVideo=MACH_RestoreVideo; return RC_SUCCESS; }
/* Detect and map the BIOS address */ int pci_BIOS_address_map(unsigned bus_device_func) { DWORD orig; DWORD addr; if (pci_read_dword(bus_device_func, 0x30, &orig) != 0) return -1; log_std(("pci: bios reported addr %08lx\n", (unsigned long)orig)); addr = orig & 0xfffe0000; if (pci_BIOS_address_map_check(addr)!=0) { addr = 0x000c0000; if (pci_BIOS_address_map_check(addr)!=0) { log_std(("pci: bios not found\n")); return -1; } } return 0; }
bool pci_device_get_next(struct pci_address* addr, int16_t class_id, int16_t sub_class, pci_device* result) { uint32_t* res_device_ptr = (uint32_t*)(result); for(; addr->bus < MAX_PCI_BUS_NR; addr->bus++) { for(; addr->device < MAX_PCI_BUS_DEV_NR; addr->device++) { for(; addr->func < MAX_FUNC_PER_PCI_BUS_DEV; addr->func++) { if(pci_read_word(addr, PCI_VENDOR_ID_REG_OFFSET) == PCI_VENDOR_ID_NO_DEVICE) continue; if(class_id != -1 && pci_read_byte(addr, PCI_DEV_CLASS_REG_OFFSET) != class_id) continue; if(sub_class != -1 && pci_read_byte(addr, PCI_DEV_SUB_CLASS_REG_OFFSET) != sub_class) continue; // Device found, read in the entire configuration space for (uint8_t i = 0; i < 64; i++) res_device_ptr[i] = pci_read_dword(addr, (i << 2)); return true; } // Ensure we scan all functions on the next device addr->func = 0; } // Ensure we scan all devices on the next bus addr->device = 0; } return false; // No more devices }
k_main() // like main { k_clear_screen(); k_puts("Welcome to MoOS version 0.1 (" BUILDTAG ")\n"); k_puts("\n"); if (pci_is_available()) { k_puts(" Detected a PCI bus\n"); } else { k_puts(" No PCI bus detected\n"); } // Try to find PCI devices unsigned int i, j, k; for (i=0; i<256; i++) { for (j=0; j<32; j++) { for (k=0; k<8; k++) { unsigned int temp = pci_read_dword(i, j, k, 0); if ((temp & 0xffff) != 0xffff) { printk("PCI device on bus: %u, slot: %u, function: %u VendorId/DeviceId: %x\n", i, j, k, temp); } } } } // NE2000 code #define NS_DATAPORT 0x10 /* NatSemi-defined port window offset. */ #define NE_DATAPORT 0x10 /* NatSemi-defined port window offset. */ #define NS_RESET 0x1f /* Issue a read to reset, a write to clear. */ #define E8390_CMD 0x00 /* The command register (for all pages) */ #define E8390_STOP 0x01 /* Stop and reset the chip */ #define E8390_START 0x02 /* Start the chip, clear reset */ #define E8390_RREAD 0x08 /* Remote read */ #define E8390_NODMA 0x20 /* Remote DMA */ #define E8390_PAGE0 0x00 /* Select page chip registers */ #define E8390_PAGE1 0x40 /* using the two high-order bits */ #define E8390_PAGE2 0x80 #define E8390_PAGE3 0xC0 /* Page 3 is invalid on the real 8390. */ #define E8390_RXOFF 0x20 /* EN0_RXCR: Accept no packets */ #define E8390_TXOFF 0x02 /* EN0_TXCR: Transmitter off */ /* Page 0 register offsets. */ #define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */ #define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */ #define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */ #define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */ #define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */ #define EN0_TSR 0x04 /* Transmit status reg RD */ #define EN0_TPSR 0x04 /* Transmit starting page WR */ #define EN0_NCR 0x05 /* Number of collision reg RD */ #define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */ #define EN0_FIFO 0x06 /* FIFO RD */ #define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */ #define EN0_ISR 0x07 /* Interrupt status reg RD WR */ #define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */ #define EN0_RSARLO 0x08 /* Remote start address reg 0 */ #define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */ #define EN0_RSARHI 0x09 /* Remote start address reg 1 */ #define EN0_RCNTLO 0x0a /* Remote byte count reg WR */ #define EN0_RCNTHI 0x0b /* Remote byte count reg WR */ #define EN0_RSR 0x0c /* rx status reg RD */ #define EN0_RXCR 0x0c /* RX configuration reg WR */ #define EN0_TXCR 0x0d /* TX configuration reg WR */ #define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */ #define EN0_DCFG 0x0e /* Data configuration reg WR */ #define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */ #define EN0_IMR 0x0f /* Interrupt mask reg WR */ #define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */ unsigned char SA_prom[32]; struct {char value, offset; } program_seq[] = { {E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD}, /* Select page 0*/ {0x48, EN0_DCFG}, /* Set byte-wide (0x48) access. */ {0x00, EN0_RCNTLO}, /* Clear the count regs. */ {0x00, EN0_RCNTHI}, {0x00, EN0_IMR}, /* Mask completion irq. */ {0xFF, EN0_ISR}, {E8390_RXOFF, EN0_RXCR}, /* 0x20 Set to monitor */ {E8390_TXOFF, EN0_TXCR}, /* 0x02 and loopback mode. */ {32, EN0_RCNTLO}, {0x00, EN0_RCNTHI}, {0x00, EN0_RSARLO}, /* DMA starting at 0x0000. */ {0x00, EN0_RSARHI}, {E8390_RREAD+E8390_START, E8390_CMD}, }; int wordlength = 2; /* Read the 16 bytes of station address prom, returning 1 for an eight-bit interface and 2 for a 16-bit interface. We must first initialize registers, similar to NS8390_init(eifdev, 0). We can't reliably read the SAPROM address without this. (I learned the hard way!). */ for (i = 0; i < sizeof(program_seq)/sizeof(program_seq[0]); i++) outportb(0x300 + program_seq[i].offset, program_seq[i].value); for(i = 0; i < 32 /*sizeof(SA_prom)*/; i+=2) { SA_prom[i] = inportb(0x300 + NE_DATAPORT); SA_prom[i+1] = inportb(0x300 + NE_DATAPORT); if (SA_prom[i] != SA_prom[i+1]) wordlength = 1; } printk("Station Address PROM 0:"); for(i = 0; i < sizeof(SA_prom)/2; i++) printk(" %2.2x", SA_prom[i]); printk("\nStation Address PROM %#2x:", i); for(; i < sizeof(SA_prom); i++) printk(" %2.2x", SA_prom[i]); printk("\n"); printk("NE200 wordlength = %u\n", wordlength); if (wordlength == 2) { /* We must set the 8390 for word mode, AND RESET IT. */ int tmp; outportb(0x300 + EN0_DCFG, 0x49); tmp = inportb(0x300 + NS_RESET); outportb(0x300 + NS_RESET, tmp); /* Un-double the SA_prom values. */ for (i = 0; i < 16; i++) SA_prom[i] = SA_prom[i+i]; } // Check for NE2000 on I/O address 0x300 printk("MAC of NE2000 @0x300: "); outportb(0x300 + E8390_CMD, E8390_NODMA + E8390_PAGE1); for (i = 1; i < 6; i++) printk("%2X:", inportb(0x300 + i)); printk("%2X\n"); // End of NE2000 code init_pics(0x20, 0x28); idt_install(); isrs_install(); irq_install(); keyboard_install(); asm volatile ("sti"); for(;;); }
static inline uint32_t get_bar(uint8_t bus, uint8_t dev, uint8_t func, uint8_t id) { return pci_read_dword(bus, dev, func, 0x10 + 4 * id); }
static inline uint16_t get_vendor_id(uint8_t bus, uint8_t dev, uint8_t func) { return pci_read_dword(bus, dev, func, 0x00) & 0xFFFF; }
void pci_reg16_write(struct pci_dev *dev, uint8_t off, uint8_t val) { uint32_t oval = pci_read_dword(dev->bus, dev->dev, dev->func, off); oval = (oval & (~0xFFFFUL << (off & 2) * 8)) | (val << (off & 2) * 8); pci_write_dword(dev->bus, dev->dev, dev->func, off, oval); }
uint32_t pci_reg32_read(struct pci_dev *dev, uint8_t off) { return pci_read_dword(dev->bus, dev->dev, dev->func, off); }
uint32_t pci_config_read_dword(struct pci_device *pdev, uint32_t offset) { return pci_read_dword(pdev->bus, pdev->slot, pdev->func, offset); }