📄 sisusb.c
字号:
switch (addr & 3) { case 0: packet.header = (type << 6) | 0x0007; ret = sisusb_send_packet(sisusb, 6, &packet); *data = packet.data & 0x00ffffff; break; case 1: packet.header = (type << 6) | 0x000e; ret = sisusb_send_packet(sisusb, 6, &packet); *data = packet.data >> 8; break; case 2: packet.header = (type << 6) | 0x000c; ret = sisusb_send_packet(sisusb, 6, &packet); *data = packet.data >> 16; packet.header = (type << 6) | 0x0001; packet.address = (addr & ~3) + 4; ret |= sisusb_send_packet(sisusb, 6, &packet); *data |= ((packet.data & 0xff) << 16); break; case 3: packet.header = (type << 6) | 0x0008; ret = sisusb_send_packet(sisusb, 6, &packet); *data = packet.data >> 24; packet.header = (type << 6) | 0x0003; packet.address = (addr & ~3) + 4; ret |= sisusb_send_packet(sisusb, 6, &packet); *data |= ((packet.data & 0xffff) << 8); } return ret;}static int sisusb_read_memio_long(struct sisusb_usb_data *sisusb, int type, u32 addr, u32 *data){ struct sisusb_packet packet; int ret = 0; packet.address = addr & ~3; switch (addr & 3) { case 0: packet.header = (type << 6) | 0x000f; ret = sisusb_send_packet(sisusb, 6, &packet); *data = packet.data; break; case 1: packet.header = (type << 6) | 0x000e; ret = sisusb_send_packet(sisusb, 6, &packet); *data = packet.data >> 8; packet.header = (type << 6) | 0x0001; packet.address = (addr & ~3) + 4; ret |= sisusb_send_packet(sisusb, 6, &packet); *data |= (packet.data << 24); break; case 2: packet.header = (type << 6) | 0x000c; ret = sisusb_send_packet(sisusb, 6, &packet); *data = packet.data >> 16; packet.header = (type << 6) | 0x0003; packet.address = (addr & ~3) + 4; ret |= sisusb_send_packet(sisusb, 6, &packet); *data |= (packet.data << 16); break; case 3: packet.header = (type << 6) | 0x0008; ret = sisusb_send_packet(sisusb, 6, &packet); *data = packet.data >> 24; packet.header = (type << 6) | 0x0007; packet.address = (addr & ~3) + 4; ret |= sisusb_send_packet(sisusb, 6, &packet); *data |= (packet.data << 8); } return ret;}static int sisusb_read_mem_bulk(struct sisusb_usb_data *sisusb, u32 addr, char *kernbuffer, int length, char __user *userbuffer, ssize_t *bytes_read){ int ret = 0; char buf[4]; u16 swap16; u32 swap32; (*bytes_read = 0); length &= 0x00ffffff; while (length) { switch (length) { case 1: ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, addr, &buf[0]); if (!ret) { (*bytes_read)++; if (userbuffer) { if (put_user(buf[0], (u8 __user *)userbuffer)) { return -EFAULT; } } else { kernbuffer[0] = buf[0]; } } return ret; case 2: ret |= sisusb_read_memio_word(sisusb, SISUSB_TYPE_MEM, addr, &swap16); if (!ret) { (*bytes_read) += 2; if (userbuffer) { if (put_user(swap16, (u16 __user *)userbuffer)) return -EFAULT; } else { *((u16 *)kernbuffer) = swap16; } } return ret; case 3: ret |= sisusb_read_memio_24bit(sisusb, SISUSB_TYPE_MEM, addr, &swap32); if (!ret) { (*bytes_read) += 3;#ifdef __BIG_ENDIAN buf[0] = (swap32 >> 16) & 0xff; buf[1] = (swap32 >> 8) & 0xff; buf[2] = swap32 & 0xff;#else buf[2] = (swap32 >> 16) & 0xff; buf[1] = (swap32 >> 8) & 0xff; buf[0] = swap32 & 0xff;#endif if (userbuffer) { if (copy_to_user(userbuffer, &buf[0], 3)) return -EFAULT; } else { kernbuffer[0] = buf[0]; kernbuffer[1] = buf[1]; kernbuffer[2] = buf[2]; } } return ret; default: ret |= sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, addr, &swap32); if (!ret) { (*bytes_read) += 4; if (userbuffer) { if (put_user(swap32, (u32 __user *)userbuffer)) return -EFAULT; userbuffer += 4; } else { *((u32 *)kernbuffer) = swap32; kernbuffer += 4; } addr += 4; length -= 4; } } if (ret) break; } return ret;}/* High level: Gfx (indexed) register access */#ifdef INCL_SISUSB_CONintsisusb_setreg(struct sisusb_usb_data *sisusb, int port, u8 data){ return sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);}intsisusb_getreg(struct sisusb_usb_data *sisusb, int port, u8 *data){ return sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port, data);}#endifintsisusb_setidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 data){ int ret; ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index); ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data); return ret;}intsisusb_getidxreg(struct sisusb_usb_data *sisusb, int port, u8 index, u8 *data){ int ret; ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, index); ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, data); return ret;}intsisusb_setidxregandor(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand, u8 myor){ int ret; u8 tmp; ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx); ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp); tmp &= myand; tmp |= myor; ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp); return ret;}static intsisusb_setidxregmask(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 data, u8 mask){ int ret; u8 tmp; ret = sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port, idx); ret |= sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, &tmp); tmp &= ~(mask); tmp |= (data & mask); ret |= sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, port + 1, tmp); return ret;}intsisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor){ return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));}intsisusb_setidxregand(struct sisusb_usb_data *sisusb, int port, u8 idx, u8 myand){ return(sisusb_setidxregandor(sisusb, port, idx, myand, 0x00));}/* Write/read video ram */#ifdef INCL_SISUSB_CONintsisusb_writeb(struct sisusb_usb_data *sisusb, u32 adr, u8 data){ return(sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));}intsisusb_readb(struct sisusb_usb_data *sisusb, u32 adr, u8 *data){ return(sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, adr, data));}intsisusb_copy_memory(struct sisusb_usb_data *sisusb, char *src, u32 dest, int length, size_t *bytes_written){ return(sisusb_write_mem_bulk(sisusb, dest, src, length, NULL, 0, bytes_written));}#ifdef SISUSBENDIANTESTintsisusb_read_memory(struct sisusb_usb_data *sisusb, char *dest, u32 src, int length, size_t *bytes_written){ return(sisusb_read_mem_bulk(sisusb, src, dest, length, NULL, bytes_written));}#endif#endif#ifdef SISUSBENDIANTESTstatic voidsisusb_testreadwrite(struct sisusb_usb_data *sisusb){ static char srcbuffer[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }; char destbuffer[10]; size_t dummy; int i,j; sisusb_copy_memory(sisusb, srcbuffer, sisusb->vrambase, 7, &dummy); for(i = 1; i <= 7; i++) { dev_dbg(&sisusb->sisusb_dev->dev, "sisusb: rwtest %d bytes\n", i); sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy); for(j = 0; j < i; j++) { dev_dbg(&sisusb->sisusb_dev->dev, "rwtest read[%d] = %x\n", j, destbuffer[j]); } }}#endif/* access pci config registers (reg numbers 0, 4, 8, etc) */static intsisusb_write_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 data){ struct sisusb_packet packet; int ret; packet.header = 0x008f; packet.address = regnum | 0x10000; packet.data = data; ret = sisusb_send_packet(sisusb, 10, &packet); return ret;}static intsisusb_read_pci_config(struct sisusb_usb_data *sisusb, int regnum, u32 *data){ struct sisusb_packet packet; int ret; packet.header = 0x008f; packet.address = (u32)regnum | 0x10000; ret = sisusb_send_packet(sisusb, 6, &packet); *data = packet.data; return ret;}/* Clear video RAM */static intsisusb_clear_vram(struct sisusb_usb_data *sisusb, u32 address, int length){ int ret, i; ssize_t j; if (address < sisusb->vrambase) return 1; if (address >= sisusb->vrambase + sisusb->vramsize) return 1; if (address + length > sisusb->vrambase + sisusb->vramsize) length = sisusb->vrambase + sisusb->vramsize - address; if (length <= 0) return 0; /* allocate free buffer/urb and clear the buffer */ if ((i = sisusb_alloc_outbuf(sisusb)) < 0) return -EBUSY; memset(sisusb->obuf[i], 0, sisusb->obufsize); /* We can write a length > buffer size here. The buffer * data will simply be re-used (like a ring-buffer). */ ret = sisusb_write_mem_bulk(sisusb, address, NULL, length, NULL, i, &j); /* Free the buffer/urb */ sisusb_free_outbuf(sisusb, i); return ret;}/* Initialize the graphics core (return 0 on success) * This resets the graphics hardware and puts it into * a defined mode (640x480@60Hz) */#define GETREG(r,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)#define SETREG(r,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_IO, r, d)#define SETIREG(r,i,d) sisusb_setidxreg(sisusb, r, i, d)#define GETIREG(r,i,d) sisusb_getidxreg(sisusb, r, i, d)#define SETIREGOR(r,i,o) sisusb_setidxregor(sisusb, r, i, o)#define SETIREGAND(r,i,a) sisusb_setidxregand(sisusb, r, i, a)#define SETIREGANDOR(r,i,a,o) sisusb_setidxregandor(sisusb, r, i, a, o)#define READL(a,d) sisusb_read_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)#define WRITEL(a,d) sisusb_write_memio_long(sisusb, SISUSB_TYPE_MEM, a, d)#define READB(a,d) sisusb_read_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)#define WRITEB(a,d) sisusb_write_memio_byte(sisusb, SISUSB_TYPE_MEM, a, d)static intsisusb_triggersr16(struct sisusb_usb_data *sisusb, u8 ramtype){ int ret; u8 tmp8; ret = GETIREG(SISSR, 0x16, &tmp8); if (ramtype <= 1) { tmp8 &= 0x3f; ret |= SETIREG(SISSR, 0x16, tmp8); tmp8 |= 0x80; ret |= SETIREG(SISSR, 0x16, tmp8); } else { tmp8 |= 0xc0; ret |= SETIREG(SISSR, 0x16, tmp8); tmp8 &= 0x0f; ret |= SETIREG(SISSR, 0x16, tmp8); tmp8 |= 0x80; ret |= SETIREG(SISSR, 0x16, tmp8); tmp8 &= 0x0f; ret |= SETIREG(SISSR, 0x16, tmp8); tmp8 |= 0xd0; ret |= SETIREG(SISSR, 0x16, tmp8); tmp8 &= 0x0f; ret |= SETIREG(SISSR, 0x16, tmp8); tmp8 |= 0xa0; ret |= SETIREG(SISSR, 0x16, tmp8); } return ret;}static intsisusb_getbuswidth(struct sisusb_usb_data *sisusb, int *bw, int *chab){ int ret; u8 ramtype, done = 0; u32 t0, t1, t2, t3; u32 ramptr = SISUSB_PCI_MEMBASE; ret = GETIREG(SISSR, 0x3a, &ramtype); ramtype &= 3; ret |= SETIREG(SISSR, 0x13, 0x00); if (ramtype <= 1) { ret |= SETIREG(SISSR, 0x14, 0x12); ret |= SETIREGAND(SISSR, 0x15, 0xef); } else { ret |= SETIREG(SISSR, 0x14, 0x02); } ret |= sisusb_triggersr16(sisusb, ramtype); ret |= WRITEL(ramptr + 0, 0x01234567); ret |= WRITEL(ramptr + 4, 0x456789ab); ret |= WRITEL(ramptr + 8, 0x89abcdef); ret |= WRITEL(ramptr + 12, 0xcdef0123); ret |= WRITEL(ramptr + 16, 0x55555555); ret |= WRITEL(ramptr + 20, 0x55555555); ret |= WRITEL(ramptr + 24, 0xffffffff); ret |= WRITEL(ramptr + 28, 0xffffffff); ret |= READL(ramptr + 0, &t0); ret |= READL(ramptr + 4, &t1); ret |= READL(ramptr + 8, &t2); ret |= READL(ramptr + 12, &t3); if (ramtype <= 1) { *chab = 0; *bw = 64; if ((t3 != 0xcdef0123) || (t2 != 0x89abcdef)) { if ((t1 == 0x456789ab) && (t0 == 0x01234567)) { *chab = 0; *bw = 64; ret |= SETIREGAND(SISSR, 0x14, 0xfd); } } if ((t1 != 0x456789ab) || (t0 != 0x01234567)) { *chab = 1; *bw = 64; ret |= SETIREGANDOR(SISSR, 0x14, 0xfc,0x01); ret |= sisusb_triggersr16(sisusb, ramtype); ret |= WRITEL(ramptr + 0, 0x89abcdef); ret |= WRITEL(ramptr + 4, 0xcdef0123); ret |= WRITEL(ramptr + 8, 0x55555555); ret |= WRITEL(ramptr + 12, 0x55555555); ret |= WRITEL(ramptr + 16, 0xaaaaaaaa); ret |= WRITEL(ramptr + 20, 0xaaaaaaaa); ret |= READL(ramptr + 4, &t1); if (t1 != 0xcdef0123) { *bw = 32; ret |= SETIREGOR(SISSR, 0x15, 0x10); } } } else { *chab = 0; *bw = 64; /* default: cha, bw = 64 */ done = 0; if (t1 == 0x456789ab) { if (t0 == 0x01234567) { *chab = 0; *bw = 64; done = 1; } } else { if (t0 == 0x01234567) { *chab = 0; *bw = 32; ret |= SETIREG(SISSR, 0x14, 0x00); done = 1; } } if (!done) { ret |= SETIREG(SISSR, 0x14, 0x03); ret |= sisusb_triggersr16(sisusb, ramtype); ret |= WRITEL(ramptr + 0, 0x01234567); ret |= WRITEL(ramptr + 4, 0x456789ab); ret |= WRITEL(ramptr + 8, 0x89abcdef); ret |= WRITEL(ramptr + 12, 0xcdef0123); ret |= WRITEL(ramptr + 16, 0x55555555); ret |= WRITEL(ramptr + 20, 0x55555555); ret |= WRITEL(ramptr + 24, 0xffffffff); ret |= WRITEL(ramptr + 28, 0xffffffff); ret |= READL(ramptr + 0, &t0); ret |= READL(ramptr + 4, &t1); if (t1 == 0x456789ab) { if (t0 == 0x01234567) { *chab = 1; *bw = 64; return ret; } /* else error */ } else { if (t0 == 0x01234567) { *chab = 1; *bw = 32; ret |= SETIREG(SISSR, 0x14, 0x01); } /* else error */ } } } return ret;}static intsisusb_verify_mclk(struct sisusb_usb_data *sisusb){ int ret = 0; u32 ramptr = SISUSB_PCI_MEMBASE; u8 tmp1, tmp2, i, j; ret |= WRITEB(ramptr, 0xaa); ret |= WRITEB(ramptr + 16, 0x55);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -