📄 mpc85xx.c
字号:
/* * $QNXLicenseC: * Copyright 2007, QNX Software Systems. * * Licensed under the Apache License, Version 2.0 (the "License"). You * may not reproduce, modify or distribute this software except in * compliance with the License. You may obtain a copy of the License * at: http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTIES OF ANY KIND, either express or implied. * * This file may contain contributions from others, either as * contributors under the License or as licensors under other terms. * Please review this entire file for other proprietary rights or license * notices, as well as the QNX Development Suite License Guide at * http://licensing.qnx.com/license-guide/ for other information. * $ */#include <stdio.h>#include <errno.h>#include <string.h>#include <stdlib.h>#include <malloc.h>#include <unistd.h>#include <gulliver.h>#include <sys/mman.h>#include <inttypes.h>#include <signal.h>#include <setjmp.h>#include <fcntl.h>#include <sys/platform.h>#include <sys/rsrcdbmgr.h>#include <sys/slogcodes.h>#include <sys/slog.h>#include <hw/inout.h>#include "mpc85xx.h"#include <ppc/85xxintr.h>pdrvr_entry_t mpc85xx_entry = { 9, mpc85xx_attach, mpc85xx_detach, mpc85xx_cnfg_bridge, mpc85xx_read_cnfg, mpc85xx_write_cnfg, mpc85xx_special_cycle, mpc85xx_map_irq, mpc85xx_avail_irq_ads, mpc85xx_map_addr}; typedef struct pci_window_structure { uint32_t base_addr; uint32_t size; uint32_t length; } pci_window_t;uint32_t mpc85xx_find_ccsr_info (){ struct asinfo_entry *asinfo; int32_t i, num; num = _syspage_ptr->asinfo.entry_size / sizeof(*asinfo); asinfo = SYSPAGE_ENTRY (asinfo); for (i = 0; i < num; ++i) { char *name; name = __hwi_find_string (asinfo->name); if (strcmp (name, "immr")) { asinfo++; continue; } return ((uint32_t) asinfo->start); } return (0);} uint32_t mpc85xx_find_mem_info( uint32_t* mem_start, uint32_t* mem_size ){ struct asinfo_entry *asinfo; int32_t i, num; num = _syspage_ptr->asinfo.entry_size / sizeof( *asinfo ); asinfo = SYSPAGE_ENTRY( asinfo ); for( i = 0; i < num; ++i ) { char *name; name = __hwi_find_string( asinfo->name ); if( strcmp( name, "ram" ) ) { asinfo++; continue; } *mem_start = ( uint32_t )asinfo->start; *mem_size = ( uint32_t )asinfo->end - ( uint32_t )asinfo->start + 1; return 1; } return 0;} int mpc85xx_get_pci_window(char* base_reg_addr, char* attr_reg_addr, pci_window_t* pci_window_buf) { uint32_t offset = 0x20; int reg_count = 8; int pci_count = 0; uint32_t attr_reg_val = 0x0; uint32_t base_reg_val = 0x0; int pci_index; int loop_1, loop_2; uint32_t temp_addr; uint32_t temp_size; uint32_t temp_length; /* Search the LAW registers for an actively mapped PCI window. */ for ( pci_index = 0; pci_index < reg_count; pci_index++ ) { attr_reg_val = in32((uintptr_t)attr_reg_addr); base_reg_val = in32((uintptr_t)base_reg_addr); if ( attr_reg_val & 0x80000000 && !(attr_reg_val & 0x00f00000) ) { pci_window_buf[pci_count].base_addr = base_reg_val << 12; pci_window_buf[pci_count].size = attr_reg_val & 0x0000003f; pci_window_buf[pci_count].length = 0x1 << (pci_window_buf[pci_count].size + 1); pci_count++; } attr_reg_addr += offset; base_reg_addr += offset; } /* Sort the PCI windows in terms of size. The largest window will be used for the memory space and the next largest for the I/O space. */ for ( loop_1 = pci_count; loop_1 > 1; loop_1-- ) { for ( loop_2 = 0; loop_2 < loop_1-1; loop_2++ ) { if ( pci_window_buf[loop_2].size < pci_window_buf[loop_2+1].size ) { temp_addr = pci_window_buf[loop_2].base_addr; temp_size = pci_window_buf[loop_2].size; temp_length = pci_window_buf[loop_2].length; pci_window_buf[loop_2].base_addr = pci_window_buf[loop_2+1].base_addr; pci_window_buf[loop_2].size = pci_window_buf[loop_2+1].size; pci_window_buf[loop_2].length = pci_window_buf[loop_2+1].length; pci_window_buf[loop_2+1].base_addr = temp_addr; pci_window_buf[loop_2+1].size = temp_size; pci_window_buf[loop_2+1].length = temp_length; } } } return pci_count; }int mpc85xx_seed(){ rsrc_alloc_t ralloc; // seed memory ralloc.start = 0x03ff0000; ralloc.end = 0xffffffff; ralloc.flags = RSRCDBMGR_MEMORY; if (rsrcdbmgr_create(&ralloc, 1) == -1) { perror("Unable to seed resource memory: "); return ENOMEM; } // seed irqs ralloc.start = 1; ralloc.end = 30; ralloc.flags = RSRCDBMGR_IRQ; if (rsrcdbmgr_create(&ralloc, 1) == -1) { perror("Unable to seed resource irqs: "); return ENOMEM; } return EOK;}intmpc85xx_avail_irq_ads(void *hdl, uint32_t bus, uint32_t devfunc, uint32_t *list, uint32_t *nelm){ uint_t dev; uint_t func; dev = ( devfunc >> 3 ) & 0x1F; func = devfunc & 0x07; if(bus) { slogf(_SLOGC_PCI, _SLOG_ERROR, "pci_server: Invalid bus %d, interrupt not assigned", bus); *nelm = 0; return (-1); } else { /* Irqs for Rev A and Pilot board PCI devices. */ switch( dev ) { case 18: case 12: if(func==0) list[0] = PPC85xx_INTR_IRQ1; if(func==1) list[0] = PPC85xx_INTR_IRQ2; if(func==2) list[0] = PPC85xx_INTR_IRQ3; if(func==3) list[0] = PPC85xx_INTR_IRQ4; break; case 19: case 13: if(func==0) list[0] = PPC85xx_INTR_IRQ4; if(func==1) list[0] = PPC85xx_INTR_IRQ1; if(func==2) list[0] = PPC85xx_INTR_IRQ2; if(func==3) list[0] = PPC85xx_INTR_IRQ3; break; case 20: case 14: if(func==0) list[0] = PPC85xx_INTR_IRQ3; if(func==1) list[0] = PPC85xx_INTR_IRQ4; if(func==2) list[0] = PPC85xx_INTR_IRQ1; if(func==3) list[0] = PPC85xx_INTR_IRQ2; break; case 21: case 15: if(func==0) list[0] = PPC85xx_INTR_IRQ2; if(func==1) list[0] = PPC85xx_INTR_IRQ3; if(func==2) list[0] = PPC85xx_INTR_IRQ4; if(func==3) list[0] = PPC85xx_INTR_IRQ1; break; default: slogf(_SLOGC_PCI, _SLOG_ERROR, "pci_server: Invalid device %d, interrupt not assigned", dev); *nelm = 0; return (-1); } *nelm = 1; return EOK; }} intmpc85xx_avail_irq_gen(void *hdl, uint32_t bus, uint32_t devfunc, uint32_t *list, uint32_t *nelm){ mpc85xx_dev_t *pdev = (mpc85xx_dev_t *)(hdl); uint_t dev; uint_t func; dev = ( devfunc >> 3 ) & 0x1F; func = devfunc & 0x07; if (bus == 0) { int dev_off = dev - pdev->devbase; if ((dev_off >= 0) && (dev_off < MAX_SLOTS)) { int irq_off; if (pdev->irqrotate) { irq_off = (func + dev_off) % MAX_SLOTS; } else { irq_off = func; } list[0] = pdev->irqbase + irq_off; *nelm = 1; return EOK; } else { slogf(_SLOGC_PCI, _SLOG_ERROR, "pci_server: Invalid device %d, interrupt not assigned", dev); } } else { slogf(_SLOGC_PCI, _SLOG_ERROR, "pci_server: Invalid bus %d, interrupt not assigned", bus); } *nelm = 0; return (-1);} intmpc85xx_config(mpc85xx_dev_t *pdev, int auto_detect){ rsrc_request_t rreq; rsrc_alloc_t ralloc; pci_window_t pci_windows[8]; int pci_count = 0; uint32_t temp, mem_cnt, mem_size; mpc85xx_seed(); memset ((char *) &rreq, 0, sizeof (rreq)); rreq.length = MPC85XX_PCI_REGISTER_LEN; rreq.align = 0; rreq.start = pdev->ccsr_base + MPC85XX_PCI_REGISTER_OFFSET; rreq.end = rreq.start + MPC85XX_PCI_REGISTER_LEN; rreq.flags = RSRCDBMGR_MEMORY; if (rsrcdbmgr_attach(&rreq, 1)) { perror("Unable to allocate PCI REGISTER memory space: "); return ENOMEM; } pdev->pci_register_base = pdev->ccsr_base + MPC85XX_PCI_REGISTER_OFFSET; if( ( pdev->register_base = mmap_device_memory( 0, MPC85XX_PCI_REGISTER_LEN, PROT_READ | PROT_WRITE | PROT_NOCACHE, 0, pdev->pci_register_base ) ) == MAP_FAILED ) { perror( "Unable to mmap PCI CNF device memory: " ); return( ENODEV ); } if ( auto_detect ) { if( ( pdev->law_register_base = mmap_device_memory( 0, MPC85XX_LAW_REGISTER_LEN, PROT_READ | PROT_WRITE | PROT_NOCACHE, 0, pdev->ccsr_base + MPC85XX_LAW_REGISTER_OFFSET ) ) == MAP_FAILED ) { perror( "Unable to mmap LAW device memory: " ); return( ENODEV ); } pci_count = mpc85xx_get_pci_window( pdev->law_register_base, pdev->law_register_base+0x8, pci_windows); munmap_device_memory(pdev->law_register_base, MPC85XX_LAW_REGISTER_LEN); if ( pci_count <= 0 ) { perror("No PCI window allocated: "); return( ENODEV); } if ( pci_count == 1 ) { pci_windows[0].size -= 1; pci_windows[0].length /= 2; pci_windows[1].base_addr = pci_windows[0].base_addr + pci_windows[0].length; pci_windows[1].size = pci_windows[0].size; pci_windows[1].length = pci_windows[0].length;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -