📄 sisusb.c
字号:
{ struct sisusb_packet packet; int ret; CLEARPACKET(&packet); packet.header = (1 << (addr & 3)) | (type << 6); packet.address = addr & ~3; ret = sisusb_send_packet(sisusb, 6, &packet); *data = (u8)(packet.data >> ((addr & 3) << 3)); return ret;}static int sisusb_read_memio_word(struct sisusb_usb_data *sisusb, int type, u32 addr, u16 *data){ struct sisusb_packet packet; int ret = 0; CLEARPACKET(&packet); packet.address = addr & ~3; switch (addr & 3) { case 0: packet.header = (type << 6) | 0x0003; ret = sisusb_send_packet(sisusb, 6, &packet); *data = (u16)(packet.data); break; case 1: packet.header = (type << 6) | 0x0006; ret = sisusb_send_packet(sisusb, 6, &packet); *data = (u16)(packet.data >> 8); break; case 2: packet.header = (type << 6) | 0x000c; ret = sisusb_send_packet(sisusb, 6, &packet); *data = (u16)(packet.data >> 16); break; case 3: packet.header = (type << 6) | 0x0008; ret = sisusb_send_packet(sisusb, 6, &packet); *data = (u16)(packet.data >> 24); packet.header = (type << 6) | 0x0001; packet.address = (addr & ~3) + 4; ret |= sisusb_send_packet(sisusb, 6, &packet); *data |= (u16)(packet.data << 8); } return ret;}static int sisusb_read_memio_24bit(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) | 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 0: return ret; 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 0 /* That does not work, as EP 2 is an OUT EP! */ default: CLEARPACKET(&packet); packet.header = 0x001f; packet.address = 0x000001a0; packet.data = 0x00000006; ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); packet.header = 0x001f; packet.address = 0x000001b0; packet.data = (length & ~3) | 0x40000000; ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); packet.header = 0x001f; packet.address = 0x000001b4; packet.data = addr; ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); packet.header = 0x001f; packet.address = 0x000001a4; packet.data = 0x00000001; ret |= sisusb_send_bridge_packet(sisusb, 10, &packet, 0); if (userbuffer) { ret |= sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_BULK_IN, (length & ~3), NULL, userbuffer, bytes_read, 0); if (!ret) userbuffer += (*bytes_read); } else { ret |= sisusb_recv_bulk_msg(sisusb, SISUSB_EP_GFX_BULK_IN, (length & ~3), kernbuffer, NULL, bytes_read, 0); if (!ret) kernbuffer += (*bytes_read); } addr += (*bytes_read); length -= (*bytes_read);#endif } 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);}#endif#ifndef INCL_SISUSB_CONstatic#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;}#ifndef INCL_SISUSB_CONstatic#endifintsisusb_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;}#ifndef INCL_SISUSB_CONstatic#endifintsisusb_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;}#ifndef INCL_SISUSB_CONstatic#endifintsisusb_setidxregor(struct sisusb_usb_data *sisusb, int port, u8 index, u8 myor){ return(sisusb_setidxregandor(sisusb, port, index, 0xff, myor));}#ifndef INCL_SISUSB_CONstatic#endifintsisusb_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_writew(struct sisusb_usb_data *sisusb, u32 adr, u16 data){ return(sisusb_write_memio_word(sisusb, SISUSB_TYPE_MEM, adr, data));}intsisusb_readw(struct sisusb_usb_data *sisusb, u32 adr, u16 *data){ return(sisusb_read_memio_word(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++) { printk(KERN_DEBUG "sisusb: rwtest %d bytes\n", i); sisusb_read_memory(sisusb, destbuffer, sisusb->vrambase, i, &dummy); for(j = 0; j < i; j++) { printk(KERN_DEBUG "sisusb: 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -