📄 sisusb.c
字号:
ret |= SETIREG(SISSR, 0x29, mclktable[(ramtype * 4) + 1]); ret |= SETIREG(SISSR, 0x2a, mclktable[(ramtype * 4) + 2]); ret |= SETIREG(SISSR, 0x2e, eclktable[ramtype * 4]); ret |= SETIREG(SISSR, 0x2f, eclktable[(ramtype * 4) + 1]); ret |= SETIREG(SISSR, 0x30, eclktable[(ramtype * 4) + 2]); ret |= SETIREG(SISSR, 0x07, 0x18); ret |= SETIREG(SISSR, 0x11, 0x0f); if (ret) continue; for (i = 0x15, j = 0; i <= 0x1b; i++, j++) { ret |= SETIREG(SISSR, i, ramtypetable1[(j*4) + ramtype]); } for (i = 0x40, j = 0; i <= 0x44; i++, j++) { ret |= SETIREG(SISCR, i, ramtypetable2[(j*4) + ramtype]); } ret |= SETIREG(SISCR, 0x49, 0xaa); ret |= SETIREG(SISSR, 0x1f, 0x00); ret |= SETIREG(SISSR, 0x20, 0xa0); ret |= SETIREG(SISSR, 0x23, 0xf6); ret |= SETIREG(SISSR, 0x24, 0x0d); ret |= SETIREG(SISSR, 0x25, 0x33); ret |= SETIREG(SISSR, 0x11, 0x0f); ret |= SETIREGOR(SISPART1, 0x2f, 0x01); ret |= SETIREGAND(SISCAP, 0x3f, 0xef); if (ret) continue; ret |= SETIREG(SISPART1, 0x00, 0x00); ret |= GETIREG(SISSR, 0x13, &tmp8); tmp8 >>= 4; ret |= SETIREG(SISPART1, 0x02, 0x00); ret |= SETIREG(SISPART1, 0x2e, 0x08); ret |= sisusb_read_pci_config(sisusb, 0x50, &tmp32); tmp32 &= 0x00f00000; tmp8 = (tmp32 == 0x100000) ? 0x33 : 0x03; ret |= SETIREG(SISSR, 0x25, tmp8); tmp8 = (tmp32 == 0x100000) ? 0xaa : 0x88; ret |= SETIREG(SISCR, 0x49, tmp8); ret |= SETIREG(SISSR, 0x27, 0x1f); ret |= SETIREG(SISSR, 0x31, 0x00); ret |= SETIREG(SISSR, 0x32, 0x11); ret |= SETIREG(SISSR, 0x33, 0x00); if (ret) continue; ret |= SETIREG(SISCR, 0x83, 0x00); ret |= sisusb_set_default_mode(sisusb, 0); ret |= SETIREGAND(SISSR, 0x21, 0xdf); ret |= SETIREGOR(SISSR, 0x01, 0x20); ret |= SETIREGOR(SISSR, 0x16, 0x0f); ret |= sisusb_triggersr16(sisusb, ramtype); /* Disable refresh */ ret |= SETIREGAND(SISSR, 0x17, 0xf8); ret |= SETIREGOR(SISSR, 0x19, 0x03); ret |= sisusb_getbuswidth(sisusb, &bw, &chab); ret |= sisusb_verify_mclk(sisusb); if (ramtype <= 1) { ret |= sisusb_get_sdram_size(sisusb, &iret, bw, chab); if (iret) { printk(KERN_ERR "sisusbvga[%d]: RAM size " "detection failed, " "assuming 8MB video RAM\n", sisusb->minor); ret |= SETIREG(SISSR,0x14,0x31); /* TODO */ } } else { printk(KERN_ERR "sisusbvga[%d]: DDR RAM device found, " "assuming 8MB video RAM\n", sisusb->minor); ret |= SETIREG(SISSR,0x14,0x31); /* *** TODO *** */ } /* Enable refresh */ ret |= SETIREG(SISSR, 0x16, ramtypetable1[4 + ramtype]); ret |= SETIREG(SISSR, 0x17, ramtypetable1[8 + ramtype]); ret |= SETIREG(SISSR, 0x19, ramtypetable1[16 + ramtype]); ret |= SETIREGOR(SISSR, 0x21, 0x20); ret |= SETIREG(SISSR, 0x22, 0xfb); ret |= SETIREG(SISSR, 0x21, 0xa5); if (ret == 0) break; } return ret;}#undef SETREG#undef GETREG#undef SETIREG#undef GETIREG#undef SETIREGOR#undef SETIREGAND#undef SETIREGANDOR#undef READL#undef WRITELstatic voidsisusb_get_ramconfig(struct sisusb_usb_data *sisusb){ u8 tmp8, tmp82, ramtype; int bw = 0; char *ramtypetext1 = NULL; const char *ramtypetext2[] = { "SDR SDRAM", "SDR SGRAM", "DDR SDRAM", "DDR SGRAM" }; static const int busSDR[4] = {64, 64, 128, 128}; static const int busDDR[4] = {32, 32, 64, 64}; static const int busDDRA[4] = {64+32, 64+32 , (64+32)*2, (64+32)*2}; sisusb_getidxreg(sisusb, SISSR, 0x14, &tmp8); sisusb_getidxreg(sisusb, SISSR, 0x15, &tmp82); sisusb_getidxreg(sisusb, SISSR, 0x3a, &ramtype); sisusb->vramsize = (1 << ((tmp8 & 0xf0) >> 4)) * 1024 * 1024; ramtype &= 0x03; switch ((tmp8 >> 2) & 0x03) { case 0: ramtypetext1 = "1 ch/1 r"; if (tmp82 & 0x10) { bw = 32; } else { bw = busSDR[(tmp8 & 0x03)]; } break; case 1: ramtypetext1 = "1 ch/2 r"; sisusb->vramsize <<= 1; bw = busSDR[(tmp8 & 0x03)]; 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; } printk(KERN_INFO "sisusbvga[%d]: %dMB %s %s, bus width %d\n", sisusb->minor, (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); down(&disconnect_sem); if (!(interface = usb_find_interface(&sisusb_driver, subminor))) { printk(KERN_ERR "sisusb[%d]: Failed to find interface\n", subminor); up(&disconnect_sem); return -ENODEV; } if (!(sisusb = usb_get_intfdata(interface))) { up(&disconnect_sem); return -ENODEV; } down(&sisusb->lock); if (!sisusb->present || !sisusb->ready) { up(&sisusb->lock); up(&disconnect_sem); return -ENODEV; } if (sisusb->isopen) { up(&sisusb->lock); up(&disconnect_sem); return -EBUSY; } if (!sisusb->devinit) { if (sisusb->sisusb_dev->speed == USB_SPEED_HIGH) { if (sisusb_init_gfxdevice(sisusb, 0)) { up(&sisusb->lock); up(&disconnect_sem); printk(KERN_ERR "sisusbvga[%d]: Failed to initialize " "device\n", sisusb->minor); return -EIO; } } else { up(&sisusb->lock); up(&disconnect_sem); printk(KERN_ERR "sisusbvga[%d]: Device not attached to " "USB 2.0 hub\n", sisusb->minor); return -EIO; } } /* Increment usage count for our sisusb */ kref_get(&sisusb->kref); sisusb->isopen = 1; file->private_data = sisusb; up(&sisusb->lock); up(&disconnect_sem); 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; int myminor; down(&disconnect_sem); if (!(sisusb = (struct sisusb_usb_data *)file->private_data)) { up(&disconnect_sem); return -ENODEV; } down(&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); } myminor = sisusb->minor; sisusb->isopen = 0; file->private_data = NULL; up(&sisusb->lock); /* decrement the usage count on our device */ kref_put(&sisusb->kref, sisus
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -