⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sisusb.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 5 页
字号:
{	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 + -