예제 #1
0
파일: pcie-xilinx.c 프로젝트: avagin/linux
/**
 * xilinx_pcie_enable_msi - Enable MSI support
 * @port: PCIe port information
 */
static int xilinx_pcie_enable_msi(struct xilinx_pcie_port *port)
{
	phys_addr_t msg_addr;

	port->msi_pages = __get_free_pages(GFP_KERNEL, 0);
	if (!port->msi_pages)
		return -ENOMEM;

	msg_addr = virt_to_phys((void *)port->msi_pages);
	pcie_write(port, 0x0, XILINX_PCIE_REG_MSIBASE1);
	pcie_write(port, msg_addr, XILINX_PCIE_REG_MSIBASE2);

	return 0;
}
예제 #2
0
파일: ssd_device.c 프로젝트: 545ssd/ssd
int wmxssd_pcie_read(char *buf, int size, unsigned int *lba)
{
   struct ssd_header headerh;
   struct ssd_header *header = &headerh;
   int pci_size;
   
   /*
   pci_size = size;
   int i;
   //create the command header
   
   // pci_size = size;
   // if(pci_size % 8)
   //    pci_size += (8 - size %8);
   // if(pci_size % 8)
   //   printk("Will is Retarted \r\n");
   
   //size
   */
   /*if((size%8) != 0) {
   pci_size += (8-(size%8)); // next largest modulo-of-8 size
}

if((size/4) <= MAX_TLP_SIZE){
}
else {
   pci_size += (128-(size%128));
}*/
   if(size>0x2000)
      printk("WHAT???!  ERROR - size %d\n", size);
   else if(size>0x1000)
   {
      wmxssd_pcie_read(buf, 0x1000, lba);
      wmxssd_pcie_read(buf+0x1000, size-0x1000, (unsigned int *)((char *)lba+0x1000));
   }
   else
   {
      pci_size = 0x1000;
      
      header->lba = htonl((int)lba);
      header->command = htonl(SSD_HEADER_READ);
      header->size = htonl(size);
      //printk("--sending read command: %d bytes to addr %x\n", ntohl(header->size), ntohl(header->lba));
      
      //send the read command to the PCIE device
      pcie_write((char *)header, sizeof(struct ssd_header));
      //read the response(data) back
      
      
      pcie_read(temp_buf, pci_size);
      memcpy(buf, temp_buf, size);
      //for(i=0; i<size; i++) buf[i] = temp_buf[i];
      //memcpy( buf, (void *)(((unsigned int )bram_disk | (unsigned int )header->lba)),  header->size);
   }
   
   return 0;
}
예제 #3
0
파일: pcie-xilinx.c 프로젝트: avagin/linux
/**
 * xilinx_pcie_clear_err_interrupts - Clear Error Interrupts
 * @port: PCIe port information
 */
static void xilinx_pcie_clear_err_interrupts(struct xilinx_pcie_port *port)
{
	struct device *dev = port->dev;
	unsigned long val = pcie_read(port, XILINX_PCIE_REG_RPEFR);

	if (val & XILINX_PCIE_RPEFR_ERR_VALID) {
		dev_dbg(dev, "Requester ID %lu\n",
			val & XILINX_PCIE_RPEFR_REQ_ID);
		pcie_write(port, XILINX_PCIE_RPEFR_ALL_MASK,
			   XILINX_PCIE_REG_RPEFR);
	}
}
예제 #4
0
파일: ssd_device.c 프로젝트: 545ssd/ssd
static void
sync_pcie(void)
{
   //char data[8192];
   char syncbyte = 0x69;

   printk("Performing 1 byte DMA sync - sent 0x%x\n",syncbyte);

   //((void **)data)[0] = (void *)htonl(0xdeadbeef);

   //sync write
   pcie_write(&syncbyte,1);
   printk("Sync done\n");
}
예제 #5
0
파일: ssd_device.c 프로젝트: 545ssd/ssd
int wmxssd_pcie_erase(int size, unsigned int *lba)
{
   struct ssd_header headerh;
   struct ssd_header *header = &headerh;
   
   //create the command header
   header->lba = htonl((int)lba);
   header->command = htonl(NAND_BLOCK_ERASE_CMD);
   header->size = htonl(size);
   //printk("--sending erase command:  addr %x\n", ntohl(header->lba));
   
   //send the erase command to the PCIE device
   pcie_write((char *)header, sizeof(struct ssd_header));
   
   
   return 0;
}
예제 #6
0
int
main (int argc, char * argv[]) {

    char arg0[32] = {};
    char arg1[64] = {
        1, 2, 3, 4, 5, 6, 7,
        8, 9, 10, 11, 12, 13, 14, 15,
        16, 17, 18, 19, 20, 21, 22, 23,
        24, 25, 26, 27, 28, 29, 30, 31, 32
    };

    pci_init();
    int sent = pcie_write(arg1, 64, 0x20000000);
    // sent = pcie_write_16_aligned(arg0, 32, 0x4000000);

    // pcie_write_16_aligned(arg1, 16, 0x0000010);

    // int sent = pcie_write(arg1, 31, 0x0002001);
    printf("sent = %d\n", sent);

    // pcie_write_1_aligned(arg+10, 0x0000001);
    // pcie_write_1_aligned(arg+10, 0x0000003);
    // pcie_write_1_aligned(arg+10, 0x0000005);
    // pcie_write_1_aligned(arg+10, 0x0000007);
    // pcie_write_1_aligned(arg+10, 0x0000009);
    // pcie_write_1_aligned(arg+10, 0x000000b);
    // pcie_write_1_aligned(arg+10, 0x000000d);
    // pcie_write_1_aligned(arg+10, 0x000000f);
    // pcie_write_1_aligned(arg+10, 0x0000000);
    // pcie_write_1_aligned(arg+10, 0x0000002);
    // pcie_write_1_aligned(arg+10, 0x0000004);
    // pcie_write_1_aligned(arg+10, 0x0000006);
    // pcie_write_1_aligned(arg+10, 0x0000008);
    // pcie_write_1_aligned(arg+10, 0x000000a);
    // pcie_write_1_aligned(arg+10, 0x000000c);
    // pcie_write_1_aligned(arg+10, 0x000000e);
    // pcie_write_8_aligned(arg, 0x0000008);
    pci_close();

    return 0;
}
예제 #7
0
파일: ssd_device.c 프로젝트: 545ssd/ssd
/*writes to our FPGA-Ramdisk from buf, size bytes, to address lba*/
int wmxssd_pcie_write(char *buf, int size, unsigned int *lba)
{
   //char data[8192];
   struct ssd_header headerh;
   struct ssd_header *header = &headerh;
   
   //for testing
   //char income[0x1000];
   //int i;
   
   int pci_size;
   /*
   pci_size = size;
   
   // if(pci_size % 8)
   //    pci_size += (8 - size % 8);
   // if(pci_size % 8)
   //    printk("Will is Retarted \r\n");
   
   //size*/
   /*if((size%8) != 0) {
   pci_size += (8-(size%8)); // next largest modulo-of-8 size
}

if((size/4) <= MAX_TLP_SIZE){
}
else {
   pci_size += (128-(size%128));
}*/
   
   //this will only work so long as it is under 0x2000
   if(size>0x2000)
      printk("WHAT???!  ERROR - size %d\n", size);
   else if(size>0x1000)
   {
      wmxssd_pcie_write(buf, 0x1000, lba);
      wmxssd_pcie_write(buf+0x1000, size-0x1000, (unsigned int *)((char *)lba+0x1000));
   }
   else
   {
      
      pci_size = 0x1000;
      //create the command header
      header->lba = htonl((int)lba);
      header->command = htonl(SSD_HEADER_WRITE);
      header->size = htonl(size);
      //printk("--sending write command: %d bytes to addr %x, firstword = %x\n", ntohl(header->size), ntohl(header->lba), *((unsigned int *) buf));
      
      //send the write command to the PCIE device
      pcie_write((char *)header, sizeof(struct ssd_header));
      //send the DATA to the PCIE device
      //use the same hack as on the firmware side - ensure 8-byte alligned
      if(size>8192)
         printk("ERROR - size %d\n", size);
      memcpy(temp_buf, buf, size);
      //for(i=0; i<size; i++) temp_buf[i] = buf[i];
      
      pcie_write(temp_buf, pci_size );
      
      
      // for testing    ---------------------------------
      /*header->lba = htonl(lba);
      header->command = htonl(SSD_HEADER_READ);
      header->size = htonl(size);
      printk("--sending read command: %d bytes to addr %x\n", ntohl(header->size), ntohl(header->lba));
      
      //send the write command to the PCIE device
      pcie_write((char *)header, sizeof(struct ssd_header));
      //send the DATA to the PCIE device
      //use the same hack as on the firmware side - ensure 8-byte alligned
      
      pcie_read(income, pci_size );
      for(i=0; i<size; i=i+4){
         if(*((int *)(income+i)) != *((int *)(buf+i)))
         printk("income[0x%x]: 0x%x --- buf[0x%x]: 0x%x \n", i, *((int *)(income+i)), i, *((int *)(buf+i)));
         }*/
      //--------------------------------------------- 
   }
   
   return 0;
   
}
예제 #8
0
파일: pcie-xilinx.c 프로젝트: avagin/linux
/**
 * xilinx_pcie_intr_handler - Interrupt Service Handler
 * @irq: IRQ number
 * @data: PCIe port information
 *
 * Return: IRQ_HANDLED on success and IRQ_NONE on failure
 */
static irqreturn_t xilinx_pcie_intr_handler(int irq, void *data)
{
	struct xilinx_pcie_port *port = (struct xilinx_pcie_port *)data;
	struct device *dev = port->dev;
	u32 val, mask, status;

	/* Read interrupt decode and mask registers */
	val = pcie_read(port, XILINX_PCIE_REG_IDR);
	mask = pcie_read(port, XILINX_PCIE_REG_IMR);

	status = val & mask;
	if (!status)
		return IRQ_NONE;

	if (status & XILINX_PCIE_INTR_LINK_DOWN)
		dev_warn(dev, "Link Down\n");

	if (status & XILINX_PCIE_INTR_ECRC_ERR)
		dev_warn(dev, "ECRC failed\n");

	if (status & XILINX_PCIE_INTR_STR_ERR)
		dev_warn(dev, "Streaming error\n");

	if (status & XILINX_PCIE_INTR_HOT_RESET)
		dev_info(dev, "Hot reset\n");

	if (status & XILINX_PCIE_INTR_CFG_TIMEOUT)
		dev_warn(dev, "ECAM access timeout\n");

	if (status & XILINX_PCIE_INTR_CORRECTABLE) {
		dev_warn(dev, "Correctable error message\n");
		xilinx_pcie_clear_err_interrupts(port);
	}

	if (status & XILINX_PCIE_INTR_NONFATAL) {
		dev_warn(dev, "Non fatal error message\n");
		xilinx_pcie_clear_err_interrupts(port);
	}

	if (status & XILINX_PCIE_INTR_FATAL) {
		dev_warn(dev, "Fatal error message\n");
		xilinx_pcie_clear_err_interrupts(port);
	}

	if (status & (XILINX_PCIE_INTR_INTX | XILINX_PCIE_INTR_MSI)) {
		val = pcie_read(port, XILINX_PCIE_REG_RPIFR1);

		/* Check whether interrupt valid */
		if (!(val & XILINX_PCIE_RPIFR1_INTR_VALID)) {
			dev_warn(dev, "RP Intr FIFO1 read error\n");
			goto error;
		}

		/* Decode the IRQ number */
		if (val & XILINX_PCIE_RPIFR1_MSI_INTR) {
			val = pcie_read(port, XILINX_PCIE_REG_RPIFR2) &
				XILINX_PCIE_RPIFR2_MSG_DATA;
		} else {
			val = (val & XILINX_PCIE_RPIFR1_INTR_MASK) >>
				XILINX_PCIE_RPIFR1_INTR_SHIFT;
			val = irq_find_mapping(port->leg_domain, val);
		}

		/* Clear interrupt FIFO register 1 */
		pcie_write(port, XILINX_PCIE_RPIFR1_ALL_MASK,
			   XILINX_PCIE_REG_RPIFR1);

		/* Handle the interrupt */
		if (IS_ENABLED(CONFIG_PCI_MSI) ||
		    !(val & XILINX_PCIE_RPIFR1_MSI_INTR))
			generic_handle_irq(val);
	}