/** * 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; }
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; }
/** * 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); } }
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"); }
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; }
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; }
/*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; }
/** * 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); }