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

📄 parport_pc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		if (ecrval & 0x02) {			/* FIFO is full. */			insb (fifo, bufp, fifo_depth);			bufp += fifo_depth;			left -= fifo_depth;			continue;		}		*bufp++ = inb (fifo);		left--;	}	port->ieee1284.phase = IEEE1284_PH_REV_IDLE;	/* Go to forward idle mode to shut the peripheral up. */	parport_frob_control (port, PARPORT_CONTROL_INIT, 0);	r = parport_wait_peripheral (port,				     PARPORT_STATUS_PAPEROUT,				     PARPORT_STATUS_PAPEROUT);	if (r)		printk (KERN_DEBUG			"%s: PE timeout FWDIDLE (%d) in ecp_read_block_pio\n",			port->name, r);	port->ieee1284.phase = IEEE1284_PH_FWD_IDLE;	/* Finish up. */	{		int lost = get_fifo_residue (port);		if (lost)			/* Shouldn't happen with compliant peripherals. */			printk (KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n",				port->name, lost);	}	return length - left;}#endif /* IEEE 1284 support */#endif /* Allowed to use FIFO/DMA */void parport_pc_inc_use_count(void){#ifdef MODULE	MOD_INC_USE_COUNT;#endif}void parport_pc_dec_use_count(void){#ifdef MODULE	MOD_DEC_USE_COUNT;#endif}struct parport_operations parport_pc_ops = {	parport_pc_write_data,	parport_pc_read_data,	parport_pc_write_control,	parport_pc_read_control,	parport_pc_frob_control,	parport_pc_read_status,	parport_pc_enable_irq,	parport_pc_disable_irq,	parport_pc_data_forward,	parport_pc_data_reverse,	parport_pc_init_state,	parport_pc_save_state,	parport_pc_restore_state,	parport_pc_inc_use_count,	parport_pc_dec_use_count,	parport_ieee1284_epp_write_data,	parport_ieee1284_epp_read_data,	parport_ieee1284_epp_write_addr,	parport_ieee1284_epp_read_addr,	parport_ieee1284_ecp_write_data,	parport_ieee1284_ecp_read_data,	parport_ieee1284_ecp_write_addr,	parport_ieee1284_write_compat,	parport_ieee1284_read_nibble,	parport_ieee1284_read_byte,};#ifdef CONFIG_PARPORT_PC_SUPERIO/* Super-IO chipset detection, Winbond, SMSC */static void __devinit show_parconfig_smsc37c669(int io, int key){	int cr1,cr4,cra,cr23,cr26,cr27,i=0;	char *modes[]={ "SPP and Bidirectional (PS/2)",				"EPP and SPP",			"ECP",			"ECP and EPP"};	outb(key,io);	outb(key,io);	outb(1,io);	cr1=inb(io+1);	outb(4,io);	cr4=inb(io+1);	outb(0x0a,io);	cra=inb(io+1);	outb(0x23,io);	cr23=inb(io+1);	outb(0x26,io);	cr26=inb(io+1);	outb(0x27,io);	cr27=inb(io+1);	outb(0xaa,io);	printk ("SMSC 37c669 LPT Config: cr_1=0x%02x, 4=0x%02x, "		"A=0x%2x, 23=0x%02x, 26=0x%02x, 27=0x%02x\n",		cr1,cr4,cra,cr23,cr26,cr27);	/* The documentation calls DMA and IRQ-Lines by letters, so	   the board maker can/will wire them	   appropriately/randomly...  G=reserved H=IDE-irq, */	printk ("SMSC LPT Config: io=0x%04x, irq=%c, dma=%c, "		"fifo threshold=%d\n", cr23*4,		(cr27 &0x0f) ? 'A'-1+(cr27 &0x0f): '-',		(cr26 &0x0f) ? 'A'-1+(cr26 &0x0f): '-', cra & 0x0f);	printk("SMSC LPT Config: enabled=%s power=%s\n",	       (cr23*4 >=0x100) ?"yes":"no", (cr1 & 4) ? "yes" : "no");	printk("SMSC LPT Config: Port mode=%s, EPP version =%s\n",	       (cr1 & 0x08 ) ? "Standard mode only (SPP)" : modes[cr4 & 0x03], 	       (cr4 & 0x40) ? "1.7" : "1.9");	/* Heuristics !  BIOS setup for this mainboard device limits	   the choices to standard settings, i.e. io-address and IRQ	   are related, however DMA can be 1 or 3, assume DMA_A=DMA1,	   DMA_C=DMA3 (this is true e.g. for TYAN 1564D Tomcat IV) */	if(cr23*4 >=0x100) { /* if active */		while((superios[i].io!= 0) && (i<NR_SUPERIOS))			i++;		if(i==NR_SUPERIOS)			printk("Super-IO: too many chips!\n");		else {			int d;			switch (cr23*4) {				case 0x3bc:					superios[i].io = 0x3bc;					superios[i].irq = 7;					break;				case 0x378:					superios[i].io = 0x378;					superios[i].irq = 7;					break;				case 0x278:					superios[i].io = 0x278;					superios[i].irq = 5;			}			d=(cr26 &0x0f);			if((d==1) || (d==3)) 				superios[i].dma= d;			else				superios[i].dma= PARPORT_DMA_NONE;		} 	}}static void __devinit show_parconfig_winbond(int io, int key){	int cr30,cr60,cr61,cr70,cr74,crf0,i=0;	char *modes[]={ "Standard (SPP) and Bidirectional(PS/2)", /* 0 */			"EPP-1.9 and SPP",			"ECP",			"ECP and EPP-1.9",			"Standard (SPP)",			"EPP-1.7 and SPP",		/* 5 */			"undefined!",			"ECP and EPP-1.7"};	char *irqtypes[]={"pulsed low, high-Z", "follows nACK"};			/* The registers are called compatible-PnP because the           register layout is modelled after ISA-PnP, the access           method is just another ... */	outb(key,io);	outb(key,io);	outb(0x07,io);   /* Register 7: Select Logical Device */	outb(0x01,io+1); /* LD1 is Parallel Port */	outb(0x30,io);	cr30=inb(io+1);	outb(0x60,io);	cr60=inb(io+1);	outb(0x61,io);	cr61=inb(io+1);	outb(0x70,io);	cr70=inb(io+1);	outb(0x74,io);	cr74=inb(io+1);	outb(0xf0,io);	crf0=inb(io+1);	outb(0xaa,io);	printk("Winbond LPT Config: cr_30=%02x 60,61=%02x%02x "	       "70=%02x 74=%02x, f0=%02x\n", cr30,cr60,cr61,cr70,cr74,crf0);	printk("Winbond LPT Config: active=%s, io=0x%02x%02x irq=%d, ", 	       (cr30 & 0x01) ? "yes":"no", cr60,cr61,cr70&0x0f );	if ((cr74 & 0x07) > 3)		printk("dma=none\n");	else		printk("dma=%d\n",cr74 & 0x07);	printk("Winbond LPT Config: irqtype=%s, ECP fifo threshold=%d\n",	       irqtypes[crf0>>7], (crf0>>3)&0x0f);	printk("Winbond LPT Config: Port mode=%s\n", modes[crf0 & 0x07]);	if(cr30 & 0x01) { /* the settings can be interrogated later ... */		while((superios[i].io!= 0) && (i<NR_SUPERIOS))			i++;		if(i==NR_SUPERIOS) 			printk("Super-IO: too many chips!\n");		else {			superios[i].io = (cr60<<8)|cr61;			superios[i].irq = cr70&0x0f;			superios[i].dma = (((cr74 & 0x07) > 3) ?					   PARPORT_DMA_NONE : (cr74 & 0x07));		}	}}static void __devinit decode_winbond(int efer, int key, int devid, int devrev, int oldid){	char *type=NULL;	int id,progif=2;	if (devid == devrev)		/* simple heuristics, we happened to read some                   non-winbond register */		return;	printk("Winbond chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x "	       "oldid=%02x\n", efer,key,devid,devrev,oldid);	id=(devid<<8) | devrev;	/* Values are from public data sheets pdf files, I can just           confirm 83977TF is correct :-) */	if      (id == 0x9771) type="83977F/AF";	else if (id == 0x9773) type="83977TF / SMSC 97w33x/97w34x";	else if (id == 0x9774) type="83977ATF";	else if ((id & ~0x0f) == 0x5270) type="83977CTF / SMSC 97w36x";	else if ((id & ~0x0f) == 0x52f0) type="83977EF / SMSC 97w35x";	else if ((id & ~0x0f) == 0x5210) type="83627";	else if ((id & ~0x0f) == 0x6010) type="83697HF";	else if ((oldid &0x0f ) == 0x0a) { type="83877F"; progif=1;}	else if ((oldid &0x0f ) == 0x0b) { type="83877AF"; progif=1;}	else if ((oldid &0x0f ) == 0x0c) { type="83877TF"; progif=1;}	else if ((oldid &0x0f ) == 0x0d) { type="83877ATF"; progif=1;}	else progif=0;	if(type==NULL) 		printk("Winbond unknown chip type\n");	else		 	printk("Winbond chip type %s\n",type);	if(progif==2)		show_parconfig_winbond(efer,key);	return;}static void __devinit decode_smsc(int efer, int key, int devid, int devrev){        char *type=NULL;	void (*func)(int io, int key);        int id;        if (devid == devrev)		/* simple heuristics, we happened to read some                   non-smsc register */		return;	func=NULL;        printk("SMSC chip at EFER=0x%x key=0x%02x devid=%02x devrev=%02x\n",	       efer,key,devid,devrev);        id=(devid<<8) | devrev;	if	(id==0x0302) {type="37c669"; func=show_parconfig_smsc37c669;}	else if	(id==0x6582) type="37c665IR";	else if	(devid==0x65) type="37c665GT";	else if	(devid==0x66) type="37c666GT";	if(type==NULL)                printk("SMSC unknown chip type\n");        else                printk("SMSC chip type %s\n",type);	if(func) (func)(efer,key);	return;}static void __devinit winbond_check(int io, int key){	int devid,devrev,oldid,x_devid,x_devrev,x_oldid;	/* First probe without key */	outb(0x20,io);	x_devid=inb(io+1);	outb(0x21,io);	x_devrev=inb(io+1);	outb(0x09,io);	x_oldid=inb(io+1);	outb(key,io);	outb(key,io);     /* Write Magic Sequence to EFER, extended                             funtion enable register */	outb(0x20,io);    /* Write EFIR, extended function index register */	devid=inb(io+1);  /* Read EFDR, extended function data register */	outb(0x21,io);	devrev=inb(io+1);	outb(0x09,io);	oldid=inb(io+1);	outb(0xaa,io);    /* Magic Seal */	if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid))		return; /* protection against false positives */	decode_winbond(io,key,devid,devrev,oldid);}static void __devinit winbond_check2(int io,int key){        int devid,devrev,oldid,x_devid,x_devrev,x_oldid;	/* First probe without the key */	outb(0x20,io+2);	x_devid=inb(io+2);	outb(0x21,io+1);	x_devrev=inb(io+2);	outb(0x09,io+1);	x_oldid=inb(io+2);        outb(key,io);     /* Write Magic Byte to EFER, extended                             funtion enable register */        outb(0x20,io+2);  /* Write EFIR, extended function index register */        devid=inb(io+2);  /* Read EFDR, extended function data register */        outb(0x21,io+1);        devrev=inb(io+2);        outb(0x09,io+1);        oldid=inb(io+2);        outb(0xaa,io);    /* Magic Seal */	if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid))		return; /* protection against false positives */        decode_winbond(io,key,devid,devrev,oldid);}static void __devinit smsc_check(int io, int key){        int id,rev,oldid,oldrev,x_id,x_rev,x_oldid,x_oldrev;	/* First probe without the key */	outb(0x0d,io);	x_oldid=inb(io+1);	outb(0x0e,io);	x_oldrev=inb(io+1);	outb(0x20,io);	x_id=inb(io+1);	outb(0x21,io);	x_rev=inb(io+1);        outb(key,io);        outb(key,io);     /* Write Magic Sequence to EFER, extended                             funtion enable register */        outb(0x0d,io);    /* Write EFIR, extended function index register */        oldid=inb(io+1);  /* Read EFDR, extended function data register */        outb(0x0e,io);        oldrev=inb(io+1);	outb(0x20,io);	id=inb(io+1);	outb(0x21,io);	rev=inb(io+1);        outb(0xaa,io);    /* Magic Seal */	if ((x_id == id) && (x_oldrev == oldrev) &&	    (x_oldid == oldid) && (x_rev == rev))		return; /* protection against false positives */        decode_smsc(io,key,oldid,oldrev);}static void __devinit detect_and_report_winbond (void){ 	printk("Winbond Super-IO detection, now testing ports 3F0,370,250,4E,2E ...\n");	winbond_check(0x3f0,0x87);	winbond_check(0x370,0x87);	winbond_check(0x2e ,0x87);	winbond_check(0x4e ,0x87);	winbond_check(0x3f0,0x86);	winbond_check2(0x250,0x88); 	winbond_check2(0x250,0x89);}static void __devinit detect_and_report_smsc (void){	printk("SMSC Super-IO detection, now testing Ports 2F0, 370 ...\n");	smsc_check(0x3f0,0x55);	smsc_check(0x370,0x55);	smsc_check(0x3f0,0x44);	smsc_check(0x370,0x44);}#endif /* CONFIG_PARPORT_PC_SUPERIO */static int __devinit get_superio_dma (struct parport *p){	int i=0;	while( (superios[i].io != p->base) && (i<NR_SUPERIOS))		i++;	if (i!=NR_SUPERIOS)		return superios[i].dma;	return PARPORT_DMA_NONE;}static int __devinit get_superio_irq (struct parport *p){	int i=0;        while( (superios[i].io != p->base) && (i<NR_SUPERIOS))                i++;        if (i!=NR_SUPERIOS)                return superios[i].irq;        return PARPORT_IRQ_NONE;}	/* --- Mode detection ------------------------------------- *//* * Checks for port existence, all ports support SPP MODE * Returns:  *         0           :  No parallel port at this adress *  PARPORT_MODE_PCSPP :  SPP port detected  *                        (if the user specified an ioport himself, *                         this shall always be the case!) * */static int __devinit parport_SPP_supported(struct parport *pb){	unsigned char r, w;	/*	 * first clear an eventually pending EPP timeout 	 * I (sailer@ife.ee.ethz.ch) have an SMSC chipset	 * that does not even respond to SPP cycles if an EPP	 * timeout is pending	 */	clear_epp_timeout(pb);	/* Do a simple read-write test to make sure the port exists. */	w = 0xc;	outb (w, CONTROL (pb));	/* Is there a control register that we can read from?  Some	 * ports don't allow reads, so read_control just returns a	 * software copy. Some ports _do_ allow reads, so bypass the	 * software copy here.  In addition, some bits aren't	 * writable. */	r = inb (CONTROL (pb));	if ((r & 0xf) == w) {		w = 0xe;		outb (w, CONTROL (pb));		r = inb (CONTROL (pb));		outb (0xc, CONTROL (pb));		if ((r & 0xf) == w)			return PARPORT_MODE_PCSPP;	}	if (user_specified)		/* That didn't work, but the user thinks there's a		 * port here. */		printk (KERN_DEBUG "parport 0x%lx (WARNING): CTR: "			"wrote 0x%02x, read 0x%02x\n", pb->base, w, r);	/* Try the data register.  The data lines aren't tri-stated at	 * this stage, so we expect back what we wrote. */	w = 0xaa;	parport_pc_write_data (pb, w);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -