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

📄 sisusb.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		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 + -