📄 sisusb.c
字号:
break; case 2: ramtypetext1 = "asymmeric"; sisusb->vramsize += sisusb->vramsize/2; bw = busDDRA[(tmp8 & 0x03)]; break; case 3: ramtypetext1 = "2 channel"; sisusb->vramsize <<= 1; bw = busDDR[(tmp8 & 0x03)]; break; } dev_info(&sisusb->sisusb_dev->dev, "%dMB %s %s, bus width %d\n", (sisusb->vramsize >> 20), ramtypetext1, ramtypetext2[ramtype], bw);}static intsisusb_do_init_gfxdevice(struct sisusb_usb_data *sisusb){ struct sisusb_packet packet; int ret; u32 tmp32; /* Do some magic */ packet.header = 0x001f; packet.address = 0x00000324; packet.data = 0x00000004; ret = sisusb_send_bridge_packet(sisusb, 10, &packet, 0); packet.header = 0x001f; packet.address = 0x00000364; packet.data = 0x00000004; ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); packet.header = 0x001f; packet.address = 0x00000384; packet.data = 0x00000004; ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); packet.header = 0x001f; packet.address = 0x00000100; packet.data = 0x00000700; ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); packet.header = 0x000f; packet.address = 0x00000004; ret |= sisusb_send_bridge_packet(sisusb, 6, &packet, 0); packet.data |= 0x17; ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); /* Init BAR 0 (VRAM) */ ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32); ret |= sisusb_write_pci_config(sisusb, 0x10, 0xfffffff0); ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32); tmp32 &= 0x0f; tmp32 |= SISUSB_PCI_MEMBASE; ret |= sisusb_write_pci_config(sisusb, 0x10, tmp32); /* Init BAR 1 (MMIO) */ ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32); ret |= sisusb_write_pci_config(sisusb, 0x14, 0xfffffff0); ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32); tmp32 &= 0x0f; tmp32 |= SISUSB_PCI_MMIOBASE; ret |= sisusb_write_pci_config(sisusb, 0x14, tmp32); /* Init BAR 2 (i/o ports) */ ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32); ret |= sisusb_write_pci_config(sisusb, 0x18, 0xfffffff0); ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32); tmp32 &= 0x0f; tmp32 |= SISUSB_PCI_IOPORTBASE; ret |= sisusb_write_pci_config(sisusb, 0x18, tmp32); /* Enable memory and i/o access */ ret |= sisusb_read_pci_config(sisusb, 0x04, &tmp32); tmp32 |= 0x3; ret |= sisusb_write_pci_config(sisusb, 0x04, tmp32); if (ret == 0) { /* Some further magic */ packet.header = 0x001f; packet.address = 0x00000050; packet.data = 0x000000ff; ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); } return ret;}/* Initialize the graphics device (return 0 on success) * This initializes the net2280 as well as the PCI registers * of the graphics board. */static intsisusb_init_gfxdevice(struct sisusb_usb_data *sisusb, int initscreen){ int ret = 0, test = 0; u32 tmp32; if (sisusb->devinit == 1) { /* Read PCI BARs and see if they have been set up */ ret |= sisusb_read_pci_config(sisusb, 0x10, &tmp32); if (ret) return ret; if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MEMBASE) test++; ret |= sisusb_read_pci_config(sisusb, 0x14, &tmp32); if (ret) return ret; if ((tmp32 & 0xfffffff0) == SISUSB_PCI_MMIOBASE) test++; ret |= sisusb_read_pci_config(sisusb, 0x18, &tmp32); if (ret) return ret; if ((tmp32 & 0xfffffff0) == SISUSB_PCI_IOPORTBASE) test++; } /* No? So reset the device */ if ((sisusb->devinit == 0) || (test != 3)) { ret |= sisusb_do_init_gfxdevice(sisusb); if (ret == 0) sisusb->devinit = 1; } if (sisusb->devinit) { /* Initialize the graphics core */ if (sisusb_init_gfxcore(sisusb) == 0) { sisusb->gfxinit = 1; sisusb_get_ramconfig(sisusb); ret |= sisusb_set_default_mode(sisusb, 1); ret |= sisusb_setup_screen(sisusb, 1, initscreen); } } return ret;}#ifdef INCL_SISUSB_CON/* Set up default text mode: - Set text mode (0x03) - Upload default font - Upload user font (if available)*/intsisusb_reset_text_mode(struct sisusb_usb_data *sisusb, int init){ int ret = 0, slot = sisusb->font_slot, i; const struct font_desc *myfont; u8 *tempbuf; u16 *tempbufb; size_t written; static const char bootstring[] = "SiSUSB VGA text console, (C) 2005 Thomas Winischhofer."; static const char bootlogo[] = "(o_ //\\ V_/_"; /* sisusb->lock is down */ if (!sisusb->SiS_Pr) return 1; sisusb->SiS_Pr->IOAddress = SISUSB_PCI_IOPORTBASE + 0x30; sisusb->SiS_Pr->sisusb = (void *)sisusb; /* Set mode 0x03 */ SiSUSBSetMode(sisusb->SiS_Pr, 0x03); if (!(myfont = find_font("VGA8x16"))) return 1; if (!(tempbuf = vmalloc(8192))) return 1; for (i = 0; i < 256; i++) memcpy(tempbuf + (i * 32), myfont->data + (i * 16), 16); /* Upload default font */ ret = sisusbcon_do_font_op(sisusb, 1, 0, tempbuf, 8192, 0, 1, NULL, 16, 0); vfree(tempbuf); /* Upload user font (and reset current slot) */ if (sisusb->font_backup) { ret |= sisusbcon_do_font_op(sisusb, 1, 2, sisusb->font_backup, 8192, sisusb->font_backup_512, 1, NULL, sisusb->font_backup_height, 0); if (slot != 2) sisusbcon_do_font_op(sisusb, 1, 0, NULL, 0, 0, 1, NULL, 16, 0); } if (init && !sisusb->scrbuf) { if ((tempbuf = vmalloc(8192))) { i = 4096; tempbufb = (u16 *)tempbuf; while (i--) *(tempbufb++) = 0x0720; i = 0; tempbufb = (u16 *)tempbuf; while (bootlogo[i]) { *(tempbufb++) = 0x0700 | bootlogo[i++]; if (!(i % 4)) tempbufb += 76; } i = 0; tempbufb = (u16 *)tempbuf + 6; while (bootstring[i]) *(tempbufb++) = 0x0700 | bootstring[i++]; ret |= sisusb_copy_memory(sisusb, tempbuf, sisusb->vrambase, 8192, &written); vfree(tempbuf); } } else if (sisusb->scrbuf) { ret |= sisusb_copy_memory(sisusb, (char *)sisusb->scrbuf, sisusb->vrambase, sisusb->scrbuf_size, &written); } if (sisusb->sisusb_cursor_size_from >= 0 && sisusb->sisusb_cursor_size_to >= 0) { sisusb_setidxreg(sisusb, SISCR, 0x0a, sisusb->sisusb_cursor_size_from); sisusb_setidxregandor(sisusb, SISCR, 0x0b, 0xe0, sisusb->sisusb_cursor_size_to); } else { sisusb_setidxreg(sisusb, SISCR, 0x0a, 0x2d); sisusb_setidxreg(sisusb, SISCR, 0x0b, 0x0e); sisusb->sisusb_cursor_size_to = -1; } slot = sisusb->sisusb_cursor_loc; if(slot < 0) slot = 0; sisusb->sisusb_cursor_loc = -1; sisusb->bad_cursor_pos = 1; sisusb_set_cursor(sisusb, slot); sisusb_setidxreg(sisusb, SISCR, 0x0c, (sisusb->cur_start_addr >> 8)); sisusb_setidxreg(sisusb, SISCR, 0x0d, (sisusb->cur_start_addr & 0xff)); sisusb->textmodedestroyed = 0; /* sisusb->lock is down */ return ret;}#endif/* fops */static intsisusb_open(struct inode *inode, struct file *file){ struct sisusb_usb_data *sisusb; struct usb_interface *interface; int subminor = iminor(inode); if (!(interface = usb_find_interface(&sisusb_driver, subminor))) return -ENODEV; if (!(sisusb = usb_get_intfdata(interface))) return -ENODEV; mutex_lock(&sisusb->lock); if (!sisusb->present || !sisusb->ready) { mutex_unlock(&sisusb->lock); return -ENODEV; } if (sisusb->isopen) { mutex_unlock(&sisusb->lock); return -EBUSY; } if (!sisusb->devinit) { if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { if (sisusb_init_gfxdevice(sisusb, 0)) { mutex_unlock(&sisusb->lock); dev_err(&sisusb->sisusb_dev->dev, "Failed to initialize device\n"); return -EIO; } } else { mutex_unlock(&sisusb->lock); dev_err(&sisusb->sisusb_dev->dev, "Device not attached to USB 2.0 hub\n"); return -EIO; } } /* Increment usage count for our sisusb */ kref_get(&sisusb->kref); sisusb->isopen = 1; file->private_data = sisusb; mutex_unlock(&sisusb->lock); return 0;}voidsisusb_delete(struct kref *kref){ struct sisusb_usb_data *sisusb = to_sisusb_dev(kref); if (!sisusb) return; if (sisusb->sisusb_dev) usb_put_dev(sisusb->sisusb_dev); sisusb->sisusb_dev = NULL; sisusb_free_buffers(sisusb); sisusb_free_urbs(sisusb);#ifdef INCL_SISUSB_CON kfree(sisusb->SiS_Pr);#endif kfree(sisusb);}static intsisusb_release(struct inode *inode, struct file *file){ struct sisusb_usb_data *sisusb; if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) return -ENODEV; mutex_lock(&sisusb->lock); if (sisusb->present) { /* Wait for all URBs to finish if device still present */ if (!sisusb_wait_all_out_complete(sisusb)) sisusb_kill_all_busy(sisusb); } sisusb->isopen = 0; file->private_data = NULL; mutex_unlock(&sisusb->lock); /* decrement the usage count on our device */ kref_put(&sisusb->kref, sisusb_delete); return 0;}static ssize_tsisusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos){ struct sisusb_usb_data *sisusb; ssize_t bytes_read = 0; int errno = 0; u8 buf8; u16 buf16; u32 buf32, address; if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) return -ENODEV; mutex_lock(&sisusb->lock); /* Sanity check */ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { mutex_unlock(&sisusb->lock); return -ENODEV; } if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE + SISUSB_PCI_IOPORTBASE; /* Read i/o ports * Byte, word and long(32) can be read. As this * emulates inX instructions, the data returned is * in machine-endianness. */ switch (count) { case 1: if (sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, address, &buf8)) errno = -EIO; else if (put_user(buf8, (u8 __user *)buffer)) errno = -EFAULT; else bytes_read = 1; break; case 2: if (sisusb_read_memio_word(sisusb, SISUSB_TYPE_IO, address, &buf16)) errno = -EIO; else if (put_user(buf16, (u16 __user *)buffer)) errno = -EFAULT; else bytes_read = 2; break; case 4: if (sisusb_read_memio_long(sisusb, SISUSB_TYPE_IO, address, &buf32)) errno = -EIO; else if (put_user(buf32, (u32 __user *)buffer)) errno = -EFAULT; else bytes_read = 4; break; default: errno = -EIO; } } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MEMBASE && (*ppos) < SISUSB_PCI_PSEUDO_MEMBASE + sisusb->vramsize) { address = (*ppos) - SISUSB_PCI_PSEUDO_MEMBASE + SISUSB_PCI_MEMBASE; /* Read video ram * Remember: Data delivered is never endian-corrected */ errno = sisusb_read_mem_bulk(sisusb, address, NULL, count, buffer, &bytes_read); if (bytes_read) errno = bytes_read; } else if ((*ppos) >= SISUSB_PCI_PSEUDO_MMIOBASE && (*ppos) < SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOSIZE) { address = (*ppos) - SISUSB_PCI_PSEUDO_MMIOBASE + SISUSB_PCI_MMIOBASE; /* Read MMIO * Remember: Data delivered is never endian-corrected */ errno = sisusb_read_mem_bulk(sisusb, address, NULL, count, buffer, &bytes_read); if (bytes_read) errno = bytes_read; } else if ((*ppos) >= SISUSB_PCI_PSEUDO_PCIBASE && (*ppos) <= SISUSB_PCI_PSEUDO_PCIBASE + 0x5c) { if (count != 4) { mutex_unlock(&sisusb->lock); return -EINVAL; } address = (*ppos) - SISUSB_PCI_PSEUDO_PCIBASE; /* Read PCI config register * Return value delivered in machine endianness. */ if (sisusb_read_pci_config(sisusb, address, &buf32)) errno = -EIO; else if (put_user(buf32, (u32 __user *)buffer)) errno = -EFAULT; else bytes_read = 4; } else { errno = -EBADFD; } (*ppos) += bytes_read; mutex_unlock(&sisusb->lock); return errno ? errno : bytes_read;}static ssize_tsisusb_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos){ struct sisusb_usb_data *sisusb; int errno = 0; ssize_t bytes_written = 0; u8 buf8; u16 buf16; u32 buf32, address; if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) return -ENODEV; mutex_lock(&sisusb->lock); /* Sanity check */ if (!sisusb->present || !sisusb->ready || !sisusb->sisusb_dev) { mutex_unlock(&sisusb->lock); return -ENODEV; } if ((*ppos) >= SISUSB_PCI_PSEUDO_IOPORTBASE && (*ppos) < SISUSB_PCI_PSEUDO_IOPORTBASE + 128) { address = (*ppos) - SISUSB_PCI_PSEUDO_IOPORTBASE + SISUSB_PCI_IOPORTBASE; /* Write i/o ports * Byte, word and long(32) can be written. As this * emulates outX instructions, the data is expected * in machine-endianness. */ switch (count) { case 1: if (get_user(bu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -