├── README.md ├── custom_device └── test_pci │ ├── Makefile │ ├── test_pci.h │ └── test_pci_driver.c ├── qemu-2.1.2 └── hw │ └── char │ ├── Makefile.objs │ └── test_pci_device.c ├── sim.sh └── user_program └── test_pci ├── Makefile └── test_pci_user.c /README.md: -------------------------------------------------------------------------------- 1 | example PCI virtual device on QEMU and its device driver / user progrm (x86 i386). 2 | -------------------------------------------------------------------------------- /custom_device/test_pci/Makefile: -------------------------------------------------------------------------------- 1 | obj-m := test_pci_driver.o 2 | 3 | all: 4 | make -C ../linux-kernel M=$(PWD) modules 5 | 6 | clean: 7 | make -C ../linux-kernel M=$(PWD) clean 8 | -------------------------------------------------------------------------------- /custom_device/test_pci/test_pci.h: -------------------------------------------------------------------------------- 1 | /* address offset */ 2 | #define TEST_PIO 0 3 | #define TEST_MEM 0 4 | 5 | #define TEST_SET_INTMASK 20 6 | #define TEST_GET_INTMASK 21 7 | 8 | #define TEST_DO 100 9 | #define TEST_DOWN_IRQ 104 10 | 11 | #define TEST_GET_CDMA_DATA 108 12 | #define TEST_CDMA_START 112 13 | #define TEST_SET_CDMA_ADDR 116 14 | #define TEST_SET_CDMA_LEN 120 15 | 16 | #define TEST_GET_SDMA_DATA 48 17 | #define TEST_SDMA_START 52 18 | #define TEST_SET_SDMA_ADDR 56 19 | #define TEST_SET_SDMA_LEN 60 20 | 21 | // PCI bar(base address register) number 22 | #define BAR_MMIO 0 23 | #define BAR_PIO 1 24 | 25 | #define PCI_VENDOR_ID_TEST 0x1234 26 | #define PCI_DEVICE_ID_TEST 0x0001 27 | 28 | #define TEST_PCI_IOSIZE 128 29 | #define TEST_PCI_MEMSIZE 2048 30 | 31 | #define TEST_PIO_DATASIZE 6 32 | #define TEST_MMIO_DATASIZE 100 33 | #define TEST_MMIO_DATANUM TEST_MMIO_DATASIZE/4 34 | 35 | #define TEST_CDMA_BUFFER_SIZE 1024 // bytes , for consistent DMA 36 | #define TEST_CDMA_BUFFER_NUM TEST_CDMA_BUFFER_SIZE/4 37 | 38 | #define TEST_SDMA_BUFFER_SIZE 1024 // bytes , for streaming DMA 39 | #define TEST_SDMA_BUFFER_NUM TEST_SDMA_BUFFER_SIZE/4 40 | 41 | // intterupt mask 42 | #define INT_DO 1 43 | #define INT_CDMA 2 44 | #define INT_SDMA 4 45 | 46 | #define CDMA_START 1 47 | #define SDMA_START 1 48 | 49 | // use for ioctl 50 | typedef struct test_ioctl_data{ 51 | int mmiodata[TEST_MMIO_DATANUM]; 52 | 53 | int cdmabuf[TEST_CDMA_BUFFER_NUM]; 54 | int sdmabuf[TEST_SDMA_BUFFER_NUM]; 55 | } test_ioctl_data; 56 | 57 | /* command for ioctl */ 58 | #define TEST_PCI_MAGIC 123 // 8bit 59 | 60 | // for mmio 61 | #define TEST_CMD_MEMREAD _IOR(TEST_PCI_MAGIC, 0, test_ioctl_data) 62 | #define TEST_CMD_MEMWRITE _IOW(TEST_PCI_MAGIC, 1, test_ioctl_data) 63 | 64 | // for irq test 65 | #define TEST_CMD_DOSOMETHING _IOW(TEST_PCI_MAGIC, 2, test_ioctl_data) 66 | #define TEST_CMD_DONESOMETHING _IOW(TEST_PCI_MAGIC, 3, test_ioctl_data) 67 | 68 | // for dma test 69 | #define TEST_CMD_CDMA_START _IOW(TEST_PCI_MAGIC, 4, test_ioctl_data) 70 | #define TEST_CMD_GET_CDMA_DATA _IOR(TEST_PCI_MAGIC, 5, test_ioctl_data) 71 | 72 | #define TEST_CMD_SDMA_START _IOW(TEST_PCI_MAGIC, 6, test_ioctl_data) 73 | #define TEST_CMD_GET_SDMA_DATA _IOR(TEST_PCI_MAGIC, 7, test_ioctl_data) 74 | -------------------------------------------------------------------------------- /custom_device/test_pci/test_pci_driver.c: -------------------------------------------------------------------------------- 1 | // pci character device driver for test_pci 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "test_pci.h" 19 | 20 | MODULE_LICENSE("GPL"); 21 | // MODULE_AUTHOR("tm"); 22 | MODULE_DESCRIPTION("device driver for test pci"); 23 | 24 | #define DRIVER_TEST_NAME "test_pci" 25 | #define DEVICE_TEST_NAME "test_pci_dev" 26 | 27 | #define TEST_PCI_DRIVER_DEBUG 28 | #ifdef TEST_PCI_DRIVER_DEBUG 29 | #define tprintk(fmt, ...) printk(KERN_ALERT "** (%3d) %-20s: " fmt, __LINE__, __func__, ## __VA_ARGS__) 30 | #else 31 | #define tprintk(fmt, ...) 32 | #endif 33 | 34 | // max device count (minor number) 35 | static int test_pci_devs_max = 1; 36 | 37 | // if test_pci_major = 0 then use dynamic allocation 38 | static unsigned int test_pci_major = 0; 39 | // get parameter from console if needed for test_pci_major when insmod 40 | module_param(test_pci_major, uint, 0); 41 | 42 | static unsigned int test_pci_minor = 0; // static allocation 43 | 44 | static dev_t test_pci_devt; // MKDEV(test_pci_major, test_pci_minor) 45 | 46 | struct test_device_data { 47 | struct pci_dev *pdev; 48 | struct cdev *cdev; 49 | 50 | // for PCI pio/mmio 51 | unsigned long pio_base, pio_flags, pio_length; 52 | unsigned long mmio_base, mmio_flags, mmio_length; 53 | char *mmio_addr; 54 | 55 | unsigned int pio_memsize; 56 | 57 | // for consistent/streaming dma 58 | dma_addr_t cdma_addr, sdma_addr; 59 | int cdma_len, sdma_len; 60 | void *cdma_buffer, *sdma_buffer; 61 | 62 | wait_queue_head_t sdma_q; 63 | }; 64 | 65 | static int sdma_done = 0; 66 | static struct test_device_data *dev_data; 67 | 68 | //----------------------------------------------------------------- 69 | // file_operations function 70 | 71 | ssize_t test_pci_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_ops) 72 | { 73 | int retval; 74 | char val; 75 | unsigned int write_num = 0; 76 | /* unsigned long pio_base; */ 77 | 78 | tprintk("count %d pos %lld\n", count, *f_ops); 79 | 80 | while(write_num < count) { 81 | tprintk("port io number:%lx\n", dev_data->pio_base+*f_ops); 82 | 83 | retval = get_user(val, &buf[write_num++]); 84 | if(retval) break; // 0 on success 85 | 86 | outb(val, dev_data->pio_base+*f_ops); 87 | (*f_ops)++; 88 | } 89 | 90 | return write_num; 91 | } 92 | 93 | // read from port io per 1 byte 94 | ssize_t test_pci_read(struct file *filp, char __user *buf, size_t count, loff_t *f_ops) 95 | { 96 | int retval; 97 | char val = 0; 98 | unsigned int read_num = 0; 99 | 100 | tprintk("count %d pos %lld\n", count, *f_ops); 101 | 102 | // read from ioport 103 | while (read_num < count) { 104 | tprintk("port io number:%lx\n", dev_data->pio_base+*f_ops); 105 | 106 | val = inb(dev_data->pio_base + *f_ops); // read 1 byte 107 | // printk("val %d\n", val); 108 | retval = put_user(val, &buf[read_num++]); 109 | if(retval) break; // 0 on success 110 | 111 | (*f_ops)++; 112 | } 113 | 114 | return read_num; 115 | } 116 | 117 | loff_t test_pci_llseek(struct file *filp, loff_t off, int whence) 118 | { 119 | loff_t newpos =-1; 120 | 121 | tprintk("lseek whence:%d\n", whence); 122 | switch(whence) { 123 | case SEEK_SET: 124 | newpos = off; 125 | break; 126 | 127 | case SEEK_CUR: 128 | newpos = filp->f_pos + off; 129 | break; 130 | 131 | case SEEK_END: 132 | newpos = dev_data->pio_memsize + off; 133 | break; 134 | 135 | default: /* can't happen */ 136 | return -EINVAL; 137 | } 138 | 139 | if (newpos < 0) return -EINVAL; 140 | 141 | filp->f_pos = newpos; 142 | return newpos; 143 | } 144 | 145 | long test_pci_uioctl(struct file *filp, unsigned int cmd, unsigned long arg) 146 | { 147 | int data[TEST_MMIO_DATANUM]; 148 | test_ioctl_data *d = arg; 149 | int n; 150 | 151 | tprintk("_cmd:%d\n", cmd); 152 | switch (cmd) { 153 | case TEST_CMD_MEMREAD : 154 | /* val = ioread32(mmio_addr); */ 155 | // ioread32_rep(mmio_addr, data, TEST_MMIO_DATANUM); 156 | 157 | memcpy_fromio(data, dev_data->mmio_addr, TEST_MMIO_DATASIZE); 158 | copy_to_user(d->mmiodata, data, TEST_MMIO_DATASIZE); 159 | break; 160 | case TEST_CMD_MEMWRITE : 161 | /* iowrite32(val, mmio_addr+TEST_MEM); */ 162 | 163 | copy_from_user(data, d->mmiodata, TEST_MMIO_DATASIZE); 164 | memcpy_toio(dev_data->mmio_addr, data, TEST_MMIO_DATASIZE); 165 | break; 166 | 167 | case TEST_CMD_CDMA_START : 168 | copy_from_user(dev_data->cdma_buffer, d->cdmabuf, TEST_CDMA_BUFFER_SIZE); 169 | wmb(); 170 | outl(CDMA_START, dev_data->pio_base + TEST_CDMA_START); 171 | break; 172 | case TEST_CMD_GET_CDMA_DATA : 173 | n = copy_to_user(d->cdmabuf, dev_data->cdma_buffer, TEST_CDMA_BUFFER_SIZE); 174 | if(n != 0){ 175 | tprintk("cannot copy all data (%d bytes in %d bytes)\n", n, TEST_CDMA_BUFFER_SIZE); 176 | } 177 | break; 178 | 179 | case TEST_CMD_SDMA_START : 180 | copy_from_user(dev_data->sdma_buffer, d->sdmabuf, TEST_SDMA_BUFFER_SIZE); 181 | dev_data->sdma_addr = pci_map_single(dev_data->pdev, dev_data->sdma_buffer, 182 | TEST_SDMA_BUFFER_SIZE, DMA_BIDIRECTIONAL); 183 | dev_data->sdma_len = TEST_SDMA_BUFFER_SIZE; 184 | wmb(); 185 | outl(dev_data->sdma_addr, dev_data->pio_base + TEST_SET_SDMA_ADDR); 186 | outl(dev_data->sdma_len, dev_data->pio_base + TEST_SET_SDMA_LEN); 187 | wmb(); 188 | outl(SDMA_START, dev_data->pio_base + TEST_SDMA_START); 189 | break; 190 | case TEST_CMD_GET_SDMA_DATA : 191 | tprintk("sdma_done %d\n", sdma_done); 192 | if(wait_event_interruptible(dev_data->sdma_q, (sdma_done == 1))) { 193 | return -ERESTARTSYS; 194 | } 195 | sdma_done = 0; 196 | 197 | pci_unmap_single(dev_data->pdev, dev_data->sdma_addr, 198 | TEST_SDMA_BUFFER_SIZE, DMA_BIDIRECTIONAL); 199 | n = copy_to_user(d->sdmabuf, dev_data->sdma_buffer, TEST_SDMA_BUFFER_SIZE); 200 | if(n != 0) { 201 | tprintk("cannot copy all data (%d bytes in %d bytes)\n", n, TEST_SDMA_BUFFER_SIZE); 202 | } 203 | break; 204 | 205 | case TEST_CMD_DOSOMETHING : 206 | outl(0, dev_data->pio_base + TEST_DO); 207 | break; 208 | 209 | default: 210 | return -EINVAL; // invalid argument(cmd) 211 | } 212 | 213 | return 0; 214 | } 215 | 216 | static int test_pci_open(struct inode *inode, struct file *file) 217 | { 218 | 219 | file->private_data = NULL; 220 | 221 | return 0; // success 222 | } 223 | 224 | static int test_pci_close(struct inode *inode, struct file *file) 225 | { 226 | 227 | if(file->private_data) { 228 | kfree(file->private_data); 229 | file->private_data = NULL; 230 | } 231 | 232 | return 0; // success 233 | } 234 | 235 | struct file_operations test_pci_fops = 236 | { 237 | .open = test_pci_open, 238 | .release = test_pci_close, 239 | .read = test_pci_read, 240 | .write = test_pci_write, 241 | .llseek = test_pci_llseek, 242 | .unlocked_ioctl = test_pci_uioctl, 243 | }; 244 | 245 | //----------------------------------------------------------------- 246 | // supported pci id type 247 | static struct pci_device_id test_pci_ids[] = 248 | { 249 | { PCI_DEVICE(PCI_VENDOR_ID_TEST, PCI_DEVICE_ID_TEST) }, 250 | { 0, }, 251 | }; 252 | 253 | // export pci_device_id 254 | MODULE_DEVICE_TABLE(pci, test_pci_ids); 255 | 256 | // interrupt handler 257 | void test_do_tasklet(unsigned long unused_data) 258 | { 259 | tprintk("tasklet called\n"); 260 | } 261 | 262 | DECLARE_TASKLET(test_tasklet, test_do_tasklet, 0); // no data 263 | 264 | irqreturn_t test_pci_handler(int irq, void *dev_id) 265 | { 266 | struct pci_dev *pdev = dev_id; 267 | char intmask; 268 | 269 | tprintk("irq handler called\n"); 270 | 271 | intmask = inb(dev_data->pio_base + TEST_GET_INTMASK); 272 | if(intmask & INT_DO) { 273 | // register tasklet 274 | tasklet_schedule(&test_tasklet); 275 | } 276 | if(intmask & INT_CDMA) { 277 | } 278 | if(intmask & INT_SDMA) { 279 | sdma_done = 1; 280 | } 281 | 282 | outb(0, dev_data->pio_base + TEST_SET_INTMASK); 283 | 284 | // down irq line 285 | outl(0, dev_data->pio_base + TEST_DOWN_IRQ); 286 | 287 | return IRQ_HANDLED; 288 | } 289 | 290 | //----------------------------------------------------------------- 291 | // pci initialization function 292 | // enable pci & register character device 293 | static int test_pci_probe (struct pci_dev *pdev, 294 | const struct pci_device_id *id) 295 | { 296 | int err; 297 | char irq; 298 | 299 | int alloc_ret = 0; 300 | int cdev_err = 0; 301 | 302 | short vendor_id, device_id; 303 | 304 | 305 | //----------------------------------------------------------------- 306 | // config PCI 307 | // enable pci device 308 | err = pci_enable_device(pdev); 309 | if(err) { 310 | printk(KERN_ERR "can't enable pci device\n"); 311 | goto error; 312 | } 313 | tprintk("PCI enabled for %s\n", DRIVER_TEST_NAME); 314 | 315 | // request PCI region 316 | // bar 0 ... MMIO 317 | dev_data->mmio_base = pci_resource_start(pdev, BAR_MMIO); 318 | dev_data->mmio_length = pci_resource_len(pdev, BAR_MMIO); 319 | dev_data->mmio_flags = pci_resource_flags(pdev, BAR_MMIO); 320 | tprintk( "mmio_base: %lx, mmio_length: %lx, mmio_flags: %lx\n", 321 | dev_data->mmio_base, dev_data->mmio_length, dev_data->mmio_flags); 322 | 323 | dev_data->mmio_addr = ioremap(dev_data->mmio_base, TEST_PCI_MEMSIZE); 324 | 325 | if(!(dev_data->mmio_flags & IORESOURCE_MEM)){ 326 | printk(KERN_ERR "BAR%d is not for mmio\n", BAR_MMIO); 327 | goto error; 328 | } 329 | 330 | err = pci_request_region(pdev, BAR_MMIO, DRIVER_TEST_NAME); 331 | if(err) { 332 | printk(KERN_ERR "%s :error pci_request_region MMIO\n", __func__); 333 | goto error; 334 | } 335 | 336 | 337 | // bar 1 ... IO port 338 | dev_data->pio_base = pci_resource_start(pdev, BAR_PIO); 339 | dev_data->pio_length = pci_resource_len(pdev, BAR_PIO); 340 | dev_data->pio_flags = pci_resource_flags(pdev, BAR_PIO); 341 | tprintk("pio_base: %lx, pio_length: %lx, pio_flags: %lx\n", 342 | dev_data->pio_base, dev_data->pio_length, dev_data->pio_flags); 343 | 344 | if(!(dev_data->pio_flags & IORESOURCE_IO)){ 345 | printk(KERN_ERR "BAR%d is not for pio\n", BAR_PIO); 346 | goto error; 347 | } 348 | 349 | err = pci_request_region(pdev, BAR_PIO, DRIVER_TEST_NAME); 350 | if(err) { 351 | printk(KERN_ERR "%s :error pci_request_region PIO\n", __func__); 352 | goto error; 353 | } 354 | 355 | // show PCI configuration data 356 | // define at include/uapi/linux/pci_regs.h 357 | pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor_id); 358 | pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id); 359 | tprintk("PCI Vendor ID:%x, Device ID:%x\n", vendor_id, device_id); 360 | 361 | 362 | dev_data->pdev = pdev; 363 | dev_data->pio_memsize = TEST_PIO_DATASIZE; 364 | 365 | tprintk("sucess allocate i/o region\n"); 366 | 367 | //----------------------------------------------------------------- 368 | // config irq 369 | // get irq number 370 | irq = pdev->irq; // same as pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &irq); 371 | tprintk("device irq: %d\n", irq); 372 | 373 | err = request_irq(irq, test_pci_handler, 0, DRIVER_TEST_NAME, pdev); 374 | if(err){ 375 | printk(KERN_ERR "%s :error request irq %d\n", __func__, irq); 376 | goto error; 377 | } 378 | 379 | 380 | //----------------------------------------------------------------- 381 | // register character device 382 | // allocate major number 383 | alloc_ret = alloc_chrdev_region(&test_pci_devt, test_pci_minor, test_pci_devs_max, DRIVER_TEST_NAME); 384 | if(alloc_ret) goto error; 385 | 386 | test_pci_major = MAJOR(test_pci_devt); 387 | 388 | dev_data->cdev = (struct cdev*)kmalloc(sizeof(struct cdev), GFP_KERNEL); 389 | if(!dev_data->cdev) goto error; 390 | 391 | cdev_init(dev_data->cdev, &test_pci_fops); 392 | dev_data->cdev->owner = THIS_MODULE; 393 | 394 | cdev_err = cdev_add(dev_data->cdev, test_pci_devt, test_pci_devs_max); 395 | if(cdev_err) goto error; 396 | 397 | tprintk("%s driver(major %d) installed.\n", DRIVER_TEST_NAME, test_pci_major); 398 | 399 | //----------------------------------------------------------------- 400 | // config DMA 401 | err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); 402 | if(err) { 403 | printk(KERN_ERR "Cannot set DMA mask\n"); 404 | goto error; 405 | } 406 | pci_set_master(pdev); 407 | 408 | // allocate consistent DMA 409 | dev_data->cdma_buffer = pci_alloc_consistent(pdev, TEST_CDMA_BUFFER_SIZE, &dev_data->cdma_addr); 410 | if(dev_data->cdma_buffer == NULL) { 411 | printk(KERN_ERR "Cannot allocate consistent DMA buffer\n"); 412 | goto error; 413 | } 414 | dev_data->cdma_len = TEST_CDMA_BUFFER_SIZE; 415 | 416 | // send consistent DMA info to device 417 | outl(dev_data->cdma_addr, dev_data->pio_base + TEST_SET_CDMA_ADDR); 418 | outl(dev_data->cdma_len, dev_data->pio_base + TEST_SET_CDMA_LEN); 419 | 420 | tprintk("cdma_addr : %x\n", dev_data->cdma_addr); 421 | 422 | // streaming DMA 423 | dev_data->sdma_buffer = kmalloc(TEST_SDMA_BUFFER_SIZE, GFP_KERNEL); 424 | if(dev_data->sdma_buffer == NULL) { 425 | printk(KERN_ERR "Cannot allocate streaming DMA buffer\n"); 426 | goto error; 427 | } 428 | init_waitqueue_head(&(dev_data->sdma_q)); 429 | 430 | return 0; 431 | 432 | error: 433 | tprintk("PCI load error\n"); 434 | if(cdev_err == 0) cdev_del(dev_data->cdev); 435 | 436 | if(alloc_ret == 0) unregister_chrdev_region(test_pci_devt, test_pci_devs_max); 437 | 438 | return -1; 439 | } 440 | 441 | static void test_pci_remove(struct pci_dev *pdev) 442 | { 443 | pci_free_consistent(dev_data->pdev, TEST_CDMA_BUFFER_SIZE, 444 | dev_data->cdma_buffer, dev_data->cdma_addr); 445 | 446 | cdev_del(dev_data->cdev); 447 | unregister_chrdev_region(test_pci_devt, test_pci_devs_max); 448 | 449 | free_irq(dev_data->pdev->irq, dev_data->pdev); 450 | 451 | iounmap(dev_data->mmio_addr); 452 | 453 | pci_release_region(dev_data->pdev, BAR_MMIO); 454 | pci_release_region(dev_data->pdev, BAR_PIO); 455 | pci_disable_device(dev_data->pdev); 456 | 457 | tprintk("%s driver (major %d) unloaded\n", DRIVER_TEST_NAME, test_pci_major); 458 | } 459 | 460 | static struct pci_driver test_pci_driver = 461 | { 462 | .name = DRIVER_TEST_NAME, 463 | .id_table = test_pci_ids, 464 | .probe = test_pci_probe, 465 | .remove = test_pci_remove, 466 | }; 467 | 468 | //----------------------------------------------------------------- 469 | // module init/exit 470 | static int __init test_pci_init(void) 471 | { 472 | dev_data = kmalloc(sizeof(struct test_device_data), GFP_KERNEL); 473 | if(!dev_data) { 474 | printk(KERN_ERR "cannot allocate device data memory\n"); 475 | return -1; // should return other value? 476 | } 477 | 478 | return pci_register_driver(&test_pci_driver); 479 | } 480 | 481 | static void __exit test_pci_exit(void) 482 | { 483 | pci_unregister_driver(&test_pci_driver); 484 | kfree(dev_data); 485 | } 486 | 487 | module_init(test_pci_init); 488 | module_exit(test_pci_exit); 489 | -------------------------------------------------------------------------------- /qemu-2.1.2/hw/char/Makefile.objs: -------------------------------------------------------------------------------- 1 | common-obj-$(CONFIG_IPACK) += ipoctal232.o 2 | common-obj-$(CONFIG_ESCC) += escc.o 3 | common-obj-$(CONFIG_PARALLEL) += parallel.o 4 | common-obj-$(CONFIG_PL011) += pl011.o 5 | common-obj-$(CONFIG_SERIAL) += serial.o serial-isa.o 6 | common-obj-$(CONFIG_SERIAL_PCI) += serial-pci.o 7 | common-obj-$(CONFIG_VIRTIO) += virtio-console.o 8 | common-obj-$(CONFIG_XILINX) += xilinx_uartlite.o 9 | common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o 10 | common-obj-$(CONFIG_CADENCE) += cadence_uart.o 11 | 12 | obj-$(CONFIG_EXYNOS4) += exynos4210_uart.o 13 | obj-$(CONFIG_COLDFIRE) += mcf_uart.o 14 | obj-$(CONFIG_OMAP) += omap_uart.o 15 | obj-$(CONFIG_SH4) += sh_serial.o 16 | obj-$(CONFIG_PSERIES) += spapr_vty.o 17 | obj-$(CONFIG_DIGIC) += digic-uart.o 18 | 19 | common-obj-$(CONFIG_ETRAXFS) += etraxfs_ser.o 20 | common-obj-$(CONFIG_ISA_DEBUG) += debugcon.o 21 | common-obj-$(CONFIG_GRLIB) += grlib_apbuart.o 22 | common-obj-$(CONFIG_IMX) += imx_serial.o 23 | common-obj-$(CONFIG_LM32) += lm32_juart.o 24 | common-obj-$(CONFIG_LM32) += lm32_uart.o 25 | common-obj-$(CONFIG_MILKYMIST) += milkymist-uart.o 26 | common-obj-$(CONFIG_SCLPCONSOLE) += sclpconsole.o sclpconsole-lm.o 27 | 28 | obj-$(CONFIG_VIRTIO) += virtio-serial-bus.o 29 | 30 | obj-$(CONFIG_PCI) += test_pci_device.o 31 | -------------------------------------------------------------------------------- /qemu-2.1.2/hw/char/test_pci_device.c: -------------------------------------------------------------------------------- 1 | // qemu test PCI virtual device 2 | 3 | #include "hw/hw.h" 4 | #include "hw/pci/pci.h" 5 | 6 | #include 7 | #include "../../../custom_device/test_pci/test_pci.h" 8 | 9 | #define TEST_PCI_DEVICE_DEBUG 10 | 11 | #ifdef TEST_PCI_DEVICE_DEBUG 12 | #define tprintf(fmt, ...) printf("## (%3d) %-20s: " fmt, __LINE__, __func__, ## __VA_ARGS__) 13 | #else 14 | #define tprintf(fmt, ...) 15 | #endif 16 | 17 | typedef struct TestPCIState { 18 | PCIDevice parent_obj; 19 | 20 | MemoryRegion mmio; 21 | MemoryRegion portio; 22 | 23 | char piodata[TEST_PIO_DATASIZE]; 24 | char mmiodata[TEST_MMIO_DATASIZE]; 25 | 26 | // for DMA operation 27 | dma_addr_t cdma_addr, sdma_addr; 28 | int cdma_len, sdma_len; 29 | int cdma_buf[TEST_CDMA_BUFFER_NUM], sdma_buf[TEST_SDMA_BUFFER_NUM]; 30 | 31 | char intmask; 32 | } TestPCIState; 33 | 34 | #define TYPE_TEST_PCI "test_pci" 35 | 36 | #define TEST_PCI(obj) \ 37 | OBJECT_CHECK(TestPCIState, (obj), TYPE_TEST_PCI) 38 | 39 | // when processing complete, raise irq line 40 | void test_do_something(TestPCIState *s); 41 | void test_do_something(TestPCIState *s) 42 | { 43 | PCIDevice *pdev = PCI_DEVICE(s); 44 | 45 | tprintf("called\n"); 46 | 47 | s->intmask |= INT_DO; 48 | // raise irq line 49 | pci_irq_assert(pdev); 50 | } 51 | 52 | void test_show_cdmabuf(TestPCIState *s); 53 | void test_show_cdmabuf(TestPCIState *s) 54 | { 55 | PCIDevice *pci_dev = PCI_DEVICE(s); 56 | int i; 57 | 58 | for (i = 0; i < TEST_CDMA_BUFFER_NUM; i++) { 59 | printf("%3d ", s->cdma_buf[i]++); 60 | } 61 | printf("\n"); 62 | 63 | pci_dma_write(pci_dev, s->cdma_addr, s->cdma_buf, s->cdma_len); 64 | 65 | s->intmask |= INT_CDMA; 66 | pci_irq_assert(pci_dev); 67 | } 68 | 69 | int comp_int(const void* a, const void*b); 70 | int comp_int(const void* a, const void*b) 71 | { 72 | return *((int *)a) - *((int *)b); 73 | } 74 | 75 | void test_show_sdmabuf(TestPCIState *s); 76 | void test_show_sdmabuf(TestPCIState *s) 77 | { 78 | PCIDevice *pci_dev = PCI_DEVICE(s); 79 | int i; 80 | 81 | for (i = 0; i < TEST_SDMA_BUFFER_NUM; i++) { 82 | printf("%3d ", s->sdma_buf[i]); 83 | } 84 | printf("\n"); 85 | qsort(s->sdma_buf, TEST_SDMA_BUFFER_NUM, sizeof(int), comp_int); 86 | pci_dma_write(pci_dev, s->sdma_addr, s->sdma_buf, s->sdma_len); 87 | 88 | s->intmask |= INT_SDMA; 89 | pci_irq_assert(pci_dev); 90 | } 91 | 92 | void test_down_irq(TestPCIState *s); 93 | void test_down_irq(TestPCIState *s) 94 | { 95 | PCIDevice *pdev = PCI_DEVICE(s); 96 | 97 | // down irq line 98 | pci_irq_deassert(pdev); 99 | } 100 | 101 | static uint64_t 102 | test_pci_mmio_read(void *opaque, hwaddr addr, unsigned size) 103 | { 104 | TestPCIState *s = opaque; 105 | tprintf("addr %ld, size %d\n", addr, size); 106 | 107 | if(addr >= TEST_MEM && addr < TEST_MEM + TEST_MMIO_DATASIZE){ 108 | return s->mmiodata[addr>>2]; // 4byte 109 | } 110 | 111 | return 0xaabbccdd; 112 | } 113 | 114 | static uint64_t 115 | test_pci_pio_read(void *opaque, hwaddr addr, unsigned size) 116 | { 117 | TestPCIState *s = opaque; 118 | tprintf("addr %ld, size %d\n", addr, size); 119 | 120 | if(addr < TEST_PIO_DATASIZE) { 121 | return s->piodata[addr]; 122 | } else { 123 | switch(addr){ 124 | case TEST_GET_INTMASK: 125 | return s->intmask; 126 | 127 | default: 128 | return 0x12345678; 129 | } 130 | } 131 | } 132 | 133 | static void 134 | test_pci_mmio_write(void *opaque, hwaddr addr, uint64_t val, 135 | unsigned size) 136 | { 137 | TestPCIState *s = opaque; 138 | 139 | tprintf("addr %ld, size %d\n", addr, size); 140 | 141 | if(addr >= TEST_MEM && addr < TEST_MEM + TEST_MMIO_DATASIZE){ 142 | s->mmiodata[addr>>2] = val; // 4byte 143 | } 144 | } 145 | 146 | static void 147 | test_pci_pio_write(void *opaque, hwaddr addr, uint64_t val, 148 | unsigned size) 149 | { 150 | TestPCIState *s = opaque; 151 | PCIDevice *pdev = PCI_DEVICE(s); 152 | 153 | // printf("%s : addr %ld, size %d\n", __func__ , addr, size); 154 | 155 | tprintf("addr %ld, size %d\n", addr, size); 156 | 157 | if(addr >= TEST_PIO && addr < TEST_PIO_DATASIZE) { 158 | s->piodata[addr] = (char)val; 159 | } else { 160 | switch (addr) { 161 | case TEST_DO: 162 | test_do_something(s); 163 | break; 164 | 165 | case TEST_SET_INTMASK: 166 | s->intmask = val; 167 | break; 168 | 169 | case TEST_DOWN_IRQ: 170 | test_down_irq(s); 171 | break; 172 | 173 | // coherent DMA 174 | case TEST_SET_CDMA_ADDR: 175 | s->cdma_addr = val; 176 | break; 177 | case TEST_SET_CDMA_LEN: 178 | s->cdma_len = val; 179 | break; 180 | case TEST_CDMA_START: 181 | pci_dma_read(pdev, s->cdma_addr, s->cdma_buf, s->cdma_len); 182 | test_show_cdmabuf(s); 183 | break; 184 | 185 | // streaming DMA 186 | case TEST_SET_SDMA_ADDR: 187 | s->sdma_addr = val; 188 | break; 189 | case TEST_SET_SDMA_LEN: 190 | s->sdma_len = val; 191 | break; 192 | case TEST_SDMA_START: 193 | pci_dma_read(pdev, s->sdma_addr, s->sdma_buf, s->sdma_len); 194 | test_show_sdmabuf(s); 195 | break; 196 | 197 | default: 198 | ; 199 | } 200 | } 201 | } 202 | 203 | static const MemoryRegionOps test_pci_mmio_ops = { 204 | .read = test_pci_mmio_read, 205 | .write = test_pci_mmio_write, 206 | .endianness = DEVICE_LITTLE_ENDIAN, 207 | .impl = { 208 | .min_access_size = 4, 209 | .max_access_size = 4, 210 | }, 211 | }; 212 | 213 | static const MemoryRegionOps test_pci_pio_ops = { 214 | .read = test_pci_pio_read, 215 | .write = test_pci_pio_write, 216 | .endianness = DEVICE_LITTLE_ENDIAN, 217 | .impl = { 218 | .min_access_size = 1, 219 | .max_access_size = 4, 220 | }, 221 | }; 222 | 223 | static int test_pci_init(PCIDevice *pdev) 224 | { 225 | TestPCIState *s = TEST_PCI(pdev); 226 | uint8_t *pci_conf; 227 | int i; 228 | 229 | pci_conf = pdev->config; 230 | pci_conf[PCI_INTERRUPT_PIN] = 1; /* if 0 no interrupt pin */ 231 | 232 | // register memory mapped io / port mapped io 233 | memory_region_init_io(&s->mmio, OBJECT(s), &test_pci_mmio_ops, s, 234 | "test_pci_mmio", TEST_PCI_MEMSIZE * 2); 235 | memory_region_init_io(&s->portio, OBJECT(s), &test_pci_pio_ops, s, 236 | "test_pci_portio", TEST_PCI_IOSIZE * 2); 237 | 238 | // set base address register 239 | pci_register_bar(pdev, BAR_MMIO, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->mmio); 240 | pci_register_bar(pdev, BAR_PIO , PCI_BASE_ADDRESS_SPACE_IO , &s->portio); 241 | 242 | // init local parameter 243 | for(i=0; ipiodata[i] = i; 245 | } 246 | for(i=0; immiodata[i] = i; 248 | } 249 | 250 | tprintf("loaded\n"); 251 | return 0; 252 | } 253 | 254 | static void 255 | test_pci_uninit(PCIDevice *pdev) 256 | { 257 | TestPCIState *s = TEST_PCI(pdev); 258 | 259 | memory_region_destroy(&s->mmio); 260 | memory_region_destroy(&s->portio); 261 | 262 | tprintf("unloaded\n"); 263 | } 264 | 265 | static void 266 | test_pci_reset(TestPCIState *s) 267 | { 268 | tprintf("done reset\n"); 269 | } 270 | 271 | static void qdev_test_pci_reset(DeviceState *ds) 272 | { 273 | TestPCIState *s = TEST_PCI(ds); 274 | test_pci_reset(s); 275 | } 276 | 277 | static void test_pci_class_init(ObjectClass *klass, void *data) 278 | { 279 | DeviceClass *dc = DEVICE_CLASS(klass); 280 | PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 281 | 282 | k->init = test_pci_init; 283 | k->exit = test_pci_uninit; 284 | k->vendor_id = PCI_VENDOR_ID_TEST; 285 | k->device_id = PCI_DEVICE_ID_TEST; 286 | k->revision = 0x00; 287 | k->class_id = PCI_CLASS_OTHERS; 288 | dc->desc = "Test PCI Virtual Device"; 289 | set_bit(DEVICE_CATEGORY_MISC, dc->categories); 290 | dc->reset = qdev_test_pci_reset; 291 | } 292 | 293 | static const TypeInfo test_pci_info = { 294 | .name = TYPE_TEST_PCI, 295 | .parent = TYPE_PCI_DEVICE, 296 | .instance_size = sizeof(TestPCIState), 297 | .class_init = test_pci_class_init, 298 | }; 299 | 300 | static void test_pci_register_types(void) 301 | { 302 | type_register_static(&test_pci_info); 303 | } 304 | 305 | type_init(test_pci_register_types) 306 | -------------------------------------------------------------------------------- /sim.sh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | 3 | if [ "$1" -eq 1 ] 4 | then 5 | emu=qemu-system-i386 6 | else 7 | emu=./qemu-2.1.2/i386-softmmu/qemu-system-i386 8 | fi 9 | 10 | if [ "$1" -eq 2 ] 11 | then 12 | sudo mount -o loop,rw -t ext2 image mnt2/ 13 | sudo cp custom_device/test_pci/test_pci_driver.ko mnt2/drivers 14 | sudo cp user_program/test_pci/test_pci_user mnt2/drivers 15 | sudo umount mnt2 16 | fi 17 | 18 | echo $emu 19 | 20 | $emu \ 21 | -kernel bzImage \ 22 | -hda image \ 23 | -append "console=ttyS0 root=/dev/sda rw panic=1" \ 24 | -nographic \ 25 | -no-reboot \ 26 | -device test_pci 27 | -------------------------------------------------------------------------------- /user_program/test_pci/Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc -m32 -Wall test_pci_user.c -o test_pci_user 3 | 4 | clean: 5 | rm test_pci_user 6 | -------------------------------------------------------------------------------- /user_program/test_pci/test_pci_user.c: -------------------------------------------------------------------------------- 1 | // test program for test_pci device 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "../../custom_device/test_pci/test_pci.h" 14 | #define DEVFILE "/dev/test_pci" 15 | 16 | int open_device(const char* filename) 17 | { 18 | int fd; 19 | 20 | fd = open(filename, O_RDWR); 21 | if(fd == -1){ 22 | printf("can't open device: %s", filename); 23 | exit(1); 24 | } 25 | 26 | printf("success: open device %s\n", filename); 27 | return fd; 28 | } 29 | 30 | void close_device(int fd) 31 | { 32 | if(close(fd) != 0){ 33 | printf("can't close device"); 34 | exit(1); 35 | } 36 | 37 | printf("success: close device\n"); 38 | } 39 | 40 | void read_device(int fd, char* buf, int size) 41 | { 42 | int i=0, ret; // ssize_t 43 | 44 | ret = read(fd, buf, size); 45 | if(ret > 0) { 46 | printf("read device : %d bytes read\n", ret); 47 | while(ret--) printf("%2d ", buf[i++]); 48 | } else { 49 | printf("read error"); 50 | } 51 | 52 | printf("\n"); 53 | } 54 | 55 | void write_device(int fd, void *buf, unsigned int size) 56 | { 57 | int ret; 58 | 59 | ret = write(fd, buf, size); 60 | if(ret < 0) { 61 | printf("write error"); 62 | } 63 | printf("write device : %d bytes write\n", ret); 64 | } 65 | 66 | void portio_test(int fd) 67 | { 68 | char buf[TEST_PIO_DATASIZE]; 69 | int i; 70 | 71 | printf("\n---- start portio test ----\n"); 72 | for (i = 0; i < TEST_PIO_DATASIZE; i++) { 73 | buf[i] = 0; 74 | } 75 | 76 | read_device(fd, buf, TEST_PIO_DATASIZE); 77 | lseek(fd, 0, SEEK_SET); 78 | 79 | for (i = 0; i < TEST_PIO_DATASIZE; i++) { 80 | buf[i] += 10; 81 | } 82 | write_device(fd, buf, sizeof(buf)); 83 | lseek(fd, 0, SEEK_SET); 84 | 85 | for (i = 0; i < TEST_PIO_DATASIZE; i++) { 86 | buf[i] = 0; 87 | } 88 | read_device(fd, buf, TEST_PIO_DATASIZE); 89 | 90 | printf("\n---- end portio test ----\n"); 91 | } 92 | 93 | void mmio_test(int fd) 94 | { 95 | int i; 96 | 97 | test_ioctl_data *d; 98 | d = malloc(sizeof(test_ioctl_data)); 99 | if(!d) exit(1); 100 | 101 | printf("\n---- start mmio test ----\n"); 102 | 103 | ioctl(fd, TEST_CMD_MEMREAD, d); 104 | for(i = 0; i < TEST_MMIO_DATANUM; i++) { 105 | printf("%2d ", d->mmiodata[i]); 106 | d->mmiodata[i] += 10; 107 | } 108 | printf("\n"); 109 | 110 | ioctl(fd, TEST_CMD_MEMWRITE, d); 111 | for(i = 0; i < TEST_MMIO_DATANUM; i++) { 112 | d->mmiodata[i] = 0; 113 | } 114 | 115 | ioctl(fd, TEST_CMD_MEMREAD, d); 116 | for(i = 0; i < TEST_MMIO_DATANUM; i++) { 117 | printf("%2d ", d->mmiodata[i]); 118 | } 119 | printf("\n"); 120 | printf("\n---- end mmio test ----\n"); 121 | 122 | free(d); 123 | } 124 | 125 | void interrupt_test(int fd) 126 | { 127 | test_ioctl_data *d; 128 | d = malloc(sizeof(test_ioctl_data)); 129 | 130 | if(!d) exit(1); 131 | printf("\n---- start interrupt test ----\n"); 132 | 133 | ioctl(fd, TEST_CMD_DOSOMETHING, d); 134 | 135 | printf("\n---- end interrupt test ----\n"); 136 | 137 | free(d); 138 | } 139 | void cdma_test(int fd) 140 | { 141 | int i; 142 | 143 | test_ioctl_data *d; 144 | d = malloc(sizeof(test_ioctl_data)); 145 | 146 | if(!d) exit(1); 147 | printf("\n---- start consistent dma test ----\n"); 148 | 149 | for(i = 0; i < TEST_CDMA_BUFFER_NUM; i++){ 150 | d->cdmabuf[i] = i; 151 | } 152 | ioctl(fd, TEST_CMD_CDMA_START, d); 153 | 154 | sleep(1); 155 | ioctl(fd, TEST_CMD_GET_CDMA_DATA, d); 156 | for(i = 0; i < TEST_CDMA_BUFFER_NUM; i++){ 157 | printf("%3d ", d->cdmabuf[i]); 158 | } 159 | printf("\n"); 160 | 161 | printf("\n---- end consistent dma test ----\n"); 162 | 163 | free(d); 164 | } 165 | 166 | void sdma_test(int fd) 167 | { 168 | int i; 169 | 170 | test_ioctl_data *d; 171 | d = malloc(sizeof(test_ioctl_data)); 172 | 173 | if(!d) exit(1); 174 | 175 | srand(123); 176 | printf("\n---- start streaming dma test ----\n"); 177 | 178 | for(i = 0; i < TEST_SDMA_BUFFER_NUM; i++){ 179 | d->sdmabuf[i] = rand()%1000; 180 | } 181 | ioctl(fd, TEST_CMD_SDMA_START, d); 182 | 183 | ioctl(fd, TEST_CMD_GET_SDMA_DATA, d); 184 | for(i = 0; i < TEST_SDMA_BUFFER_NUM; i++){ 185 | printf("%3d ", d->sdmabuf[i]); 186 | } 187 | printf("\n"); 188 | 189 | printf("\n---- end streaming dma test ----\n"); 190 | 191 | free(d); 192 | } 193 | 194 | int main(int argc, char const* argv[]) 195 | { 196 | int fd; 197 | 198 | fd = open_device(DEVFILE); 199 | 200 | portio_test(fd); 201 | mmio_test(fd); 202 | interrupt_test(fd); 203 | cdma_test(fd); 204 | sdma_test(fd); 205 | 206 | close_device(fd); 207 | return 0; 208 | } 209 | --------------------------------------------------------------------------------