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

📄 ser_a2232.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
   A2232 buffer any more. */	struct a2232_port *port = (struct a2232_port *) tty->driver_data;	port->throttle_input = -1;}static void a2232_unthrottle(struct tty_struct *tty){/* Unthrottle: dual to "throttle()" above. */	struct a2232_port *port = (struct a2232_port *) tty->driver_data;	port->throttle_input = 0;}static int  a2232_open(struct tty_struct * tty, struct file * filp){/* More or less stolen from other drivers. */	int line;	int retval;	struct a2232_port *port;	line = MINOR(tty->device);	port = &a2232_ports[line];		tty->driver_data = port;	port->gs.tty = tty;	port->gs.count++;	retval = gs_init_port(&port->gs);	if (retval) {		port->gs.count--;		return retval;	}	port->gs.flags |= GS_ACTIVE;	if (port->gs.count == 1) {		MOD_INC_USE_COUNT;	}	retval = gs_block_til_ready(port, filp);	if (retval) {		MOD_DEC_USE_COUNT;		port->gs.count--;		return retval;	}	if ((port->gs.count == 1) && (port->gs.flags & ASYNC_SPLIT_TERMIOS)){		if (tty->driver.subtype == A2232_TTY_SUBTYPE_NORMAL)			*tty->termios = port->gs.normal_termios;		else 			*tty->termios = port->gs.callout_termios;		a2232_set_real_termios (port);	}	port->gs.session = current->session;	port->gs.pgrp = current->pgrp;	a2232_enable_rx_interrupts(port);		return 0;}/*** END OF FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/static __inline__ volatile struct a2232status *a2232stat(unsigned int board, unsigned int portonboard){	volatile struct a2232memory *mem = a2232mem(board);	return &(mem->Status[portonboard]);}static __inline__ volatile struct a2232memory *a2232mem (unsigned int board){	return (volatile struct a2232memory *) ZTWO_VADDR( zd_a2232[board]->resource.start );}static __inline__ void a2232_receive_char(	struct a2232_port *port,						int ch, int err ){/* 	Mostly stolen from other drivers.	Maybe one could implement a more efficient version by not only	transferring one character at a time.*/	struct tty_struct *tty = port->gs.tty;		if (tty->flip.count >= TTY_FLIPBUF_SIZE)		return;	tty->flip.count++;#if 0	switch(err) {	case TTY_BREAK:		break;	case TTY_PARITY:		break;	case TTY_OVERRUN:		break;	case TTY_FRAME:		break;	}#endif	*tty->flip.flag_buf_ptr++ = err;	*tty->flip.char_buf_ptr++ = ch;	tty_flip_buffer_push(tty);}static void a2232_vbl_inter(int irq, void *data, struct pt_regs *fp){#if A2232_IOBUFLEN != 256#error "Re-Implement a2232_vbl_inter()!"#endifstruct a2232_port *port;volatile struct a2232memory *mem;volatile struct a2232status *status;unsigned char newhead;unsigned char bufpos; /* Must be unsigned char. We need the modulo-256 arithmetics */unsigned char ncd, ocd, ccd; /* names consistent with the NetBSD driver */volatile u_char *ibuf, *cbuf, *obuf;int ch, err, n, p;	for (n = 0; n < nr_a2232; n++){		/* for every completely initialized A2232 board */		mem = a2232mem(n);		for (p = 0; p < NUMLINES; p++){	/* for every port on this board */			err = 0;			port = &a2232_ports[n*NUMLINES+p];			if ( port->gs.flags & GS_ACTIVE ){ /* if the port is used */				status = a2232stat(n,p);				if (!port->disable_rx && !port->throttle_input){ /* If input is not disabled */					newhead = status->InHead;               /* 65EC02 write pointer */					bufpos = status->InTail;					/* check for input for this port */					if (newhead != bufpos) {						/* buffer for input chars/events */						ibuf = mem->InBuf[p]; 						/* data types of bytes in ibuf */						cbuf = mem->InCtl[p]; 						/* do for all chars */						while (bufpos != newhead) {							/* which type of input data? */							switch (cbuf[bufpos]) {								/* switch on input event (CD, BREAK, etc.) */							case A2232INCTL_EVENT:								switch (ibuf[bufpos++]) {								case A2232EVENT_Break:									/* TODO: Handle BREAK signal */									break;									/*	A2232EVENT_CarrierOn and A2232EVENT_CarrierOff are										handled in a separate queue and should not occur here. */								case A2232EVENT_Sync:									printk("A2232: 65EC02 software sent SYNC event, don't know what to do. Ignoring.");									break;								default:									printk("A2232: 65EC02 software broken, unknown event type %d occured.\n",ibuf[bufpos-1]);								} /* event type switch */								break; 							case A2232INCTL_CHAR:								/* Receive incoming char */								a2232_receive_char(port, ibuf[bufpos], err);								bufpos++;								break; 							default:								printk("A2232: 65EC02 software broken, unknown data type %d occured.\n",cbuf[bufpos]);								bufpos++;							} /* switch on input data type */						} /* while there's something in the buffer */						status->InTail = bufpos;            /* tell 65EC02 what we've read */											} /* if there was something in the buffer */                          				} /* If input is not disabled */				/* Now check if there's something to output */				obuf = mem->OutBuf[p];				bufpos = status->OutHead;				while ( (port->gs.xmit_cnt > 0)		&&					(!port->gs.tty->stopped)	&&					(!port->gs.tty->hw_stopped) ){	/* While there are chars to transmit */					if (((bufpos+1) & A2232_IOBUFLENMASK) != status->OutTail) { /* If the A2232 buffer is not full */						ch = port->gs.xmit_buf[port->gs.xmit_tail];					/* get the next char to transmit */						port->gs.xmit_tail = (port->gs.xmit_tail+1) & (SERIAL_XMIT_SIZE-1); /* modulo-addition for the gs.xmit_buf ring-buffer */						obuf[bufpos++] = ch;																/* put it into the A2232 buffer */						port->gs.xmit_cnt--;					}					else{																									/* If A2232 the buffer is full */						break;																							/* simply stop filling it. */					}																	}									status->OutHead = bufpos;									/* WakeUp if output buffer runs low */				if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.tty) {					if ((port->gs.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && port->gs.tty->ldisc.write_wakeup){						(port->gs.tty->ldisc.write_wakeup)(port->gs.tty);					}					wake_up_interruptible(&port->gs.tty->write_wait);				}			} // if the port is used		} // for every port on the board					/* Now check the CD message queue */		newhead = mem->Common.CDHead;		bufpos = mem->Common.CDTail;		if (newhead != bufpos){				/* There are CD events in queue */			ocd = mem->Common.CDStatus; 		/* get old status bits */			while (newhead != bufpos){		/* read all events */				ncd = mem->CDBuf[bufpos++]; 	/* get one event */				ccd = ncd ^ ocd; 		/* mask of changed lines */				ocd = ncd; 			/* save new status bits */				for(p=0; p < NUMLINES; p++){	/* for all ports */					if (ccd & 1){		/* this one changed */						struct a2232_port *port = &a2232_ports[n*7+p];						port->cd_status = !(ncd & 1); /* ncd&1 <=> CD is now off */						if (!(port->gs.flags & ASYNC_CHECK_CD))							;	/* Don't report DCD changes */						else if (port->cd_status) { // if DCD on: DCD went UP!							if (~(port->gs.flags & ASYNC_NORMAL_ACTIVE) ||							    ~(port->gs.flags & ASYNC_CALLOUT_ACTIVE)) {								/* Are we blocking in open?*/								wake_up_interruptible(&port->gs.open_wait);							}						}						else { // if DCD off: DCD went DOWN!							if (!((port->gs.flags & ASYNC_CALLOUT_ACTIVE) &&							      (port->gs.flags & ASYNC_CALLOUT_NOHUP))) {								if (port->gs.tty)									tty_hangup (port->gs.tty);							}						}											} // if CD changed for this port					ccd >>= 1;					ncd >>= 1;									/* Shift bits for next line */				} // for every port			} // while CD events in queue			mem->Common.CDStatus = ocd; /* save new status */			mem->Common.CDTail = bufpos; /* remove events */		} // if events in CD queue			} // for every completely initialized A2232 board}static void a2232_init_portstructs(void){	struct a2232_port *port;	int i;	for (i = 0; i < MAX_A2232_BOARDS*NUMLINES; i++) {		port = a2232_ports + i;		port->which_a2232 = i/NUMLINES;		port->which_port_on_a2232 = i%NUMLINES;		port->disable_rx = port->throttle_input = port->cd_status = 0;		port->gs.callout_termios = tty_std_termios;		port->gs.normal_termios = tty_std_termios;		port->gs.magic = A2232_MAGIC;		port->gs.close_delay = HZ/2;		port->gs.closing_wait = 30 * HZ;		port->gs.rd = &a2232_real_driver;#ifdef NEW_WRITE_LOCKING		init_MUTEX(&(port->gs.port_write_sem));#endif		init_waitqueue_head(&port->gs.open_wait);		init_waitqueue_head(&port->gs.close_wait);	}}static int a2232_init_drivers(void){	int error;	memset(&a2232_driver, 0, sizeof(a2232_driver));	a2232_driver.magic = TTY_DRIVER_MAGIC;	a2232_driver.driver_name = "commodore_a2232";	a2232_driver.name = "ttyY";	a2232_driver.major = A2232_NORMAL_MAJOR;	a2232_driver.num = NUMLINES * nr_a2232;	a2232_driver.type = TTY_DRIVER_TYPE_SERIAL;	a2232_driver.subtype = A2232_TTY_SUBTYPE_NORMAL;	a2232_driver.init_termios = tty_std_termios;	a2232_driver.init_termios.c_cflag =		B9600 | CS8 | CREAD | HUPCL | CLOCAL;	a2232_driver.flags = TTY_DRIVER_REAL_RAW;	a2232_driver.refcount = &a2232_refcount;	a2232_driver.table = a2232_table;	a2232_driver.termios = a2232_termios;	a2232_driver.termios_locked = a2232_termios_locked;	a2232_driver.open = a2232_open;	a2232_driver.close = gs_close;	a2232_driver.write = gs_write;	a2232_driver.put_char = gs_put_char;	a2232_driver.flush_chars = gs_flush_chars;	a2232_driver.write_room = gs_write_room;	a2232_driver.chars_in_buffer = gs_chars_in_buffer;	a2232_driver.flush_buffer = gs_flush_buffer;	a2232_driver.ioctl = a2232_ioctl;	a2232_driver.throttle = a2232_throttle;	a2232_driver.unthrottle = a2232_unthrottle;	a2232_driver.set_termios = gs_set_termios;	a2232_driver.stop = gs_stop;	a2232_driver.start = gs_start;	a2232_driver.hangup = gs_hangup;	a2232_callout_driver = a2232_driver;	a2232_callout_driver.name = "cuy";	a2232_callout_driver.major = A2232_CALLOUT_MAJOR;	a2232_callout_driver.subtype = A2232_TTY_SUBTYPE_CALLOUT;	if ((error = tty_register_driver(&a2232_driver))) {		printk(KERN_ERR "A2232: Couldn't register A2232 driver, error = %d\n",		       error);		return 1;	}	if ((error = tty_register_driver(&a2232_callout_driver))) {		tty_unregister_driver(&a2232_driver);		printk(KERN_ERR "A2232: Couldn't register A2232 callout driver, error = %d\n",		       error);		return 1;	}	return 0;}int a2232board_init(void){	struct zorro_dev *z;	unsigned int boardaddr;	int bcount;	short start;	u_char *from;	volatile u_char *to;	volatile struct a2232memory *mem;#ifdef __SMP__	return -ENODEV;	/* This driver is not SMP aware. Is there an SMP ZorroII-bus-machine? */#endif	if (!MACH_IS_AMIGA){		return -ENODEV;	}	printk("Commodore A2232 driver initializing.\n"); /* Say that we're alive. */	z = NULL;	nr_a2232 = 0;	while ( (z = zorro_find_device(ZORRO_WILDCARD, z)) ){		if (	(z->id != ZORRO_PROD_CBM_A2232_PROTOTYPE) && 			(z->id != ZORRO_PROD_CBM_A2232)	){			continue;	// The board found was no A2232		}		if (!zorro_request_device(z,"A2232 driver"))			continue;		printk("Commodore A2232 found (#%d).\n",nr_a2232);		zd_a2232[nr_a2232] = z;		boardaddr = ZTWO_VADDR( z->resource.start );		printk("Board is located at address 0x%x, size is 0x%x.\n", boardaddr, (unsigned int) ((z->resource.end+1) - (z->resource.start)));		mem = (volatile struct a2232memory *) boardaddr;		(void) mem->Enable6502Reset;   /* copy the code across to the board */		to = (u_char *)mem;  from = a2232_65EC02code; bcount = sizeof(a2232_65EC02code) - 2;		start = *(short *)from;		from += sizeof(start);		to += start;		while(bcount--) *to++ = *from++;		printk("65EC02 software uploaded to the A2232 memory.\n");  		mem->Common.Crystal = A2232_UNKNOWN;  /* use automatic speed check */  		/* start 6502 running */		(void) mem->ResetBoard;		printk("A2232's 65EC02 CPU up and running.\n");  		/* wait until speed detector has finished */		for (bcount = 0; bcount < 2000; bcount++) {			udelay(1000);			if (mem->Common.Crystal)				break;		}		printk((mem->Common.Crystal?"A2232 oscillator crystal detected by 65EC02 software: ":"65EC02 software could not determine A2232 oscillator crystal: "));		switch (mem->Common.Crystal){		case A2232_UNKNOWN:			printk("Unknown crystal.\n");			break; 		case A2232_NORMAL:			printk ("Normal crystal.\n");			break;		case A2232_TURBO:			printk ("Turbo crystal.\n");			break;		default:			printk ("0x%x. Huh?\n",mem->Common.Crystal);		}		nr_a2232++;	}		printk("Total: %d A2232 boards initialized.\n.", nr_a2232); /* Some status report if no card was found */	a2232_init_portstructs();	/*		a2232_init_drivers also registers the drivers. Must be here because all boards		have to be detected first.	*/	if (a2232_init_drivers()) return -ENODEV; // maybe we should use a different -Exxx?	request_irq(IRQ_AMIGA_VERTB, a2232_vbl_inter, 0, "A2232 serial VBL", a2232_driver_ID);	return 0;}#ifdef MODULEint init_module(void){	return a2232board_init();}void cleanup_module(void){	int i;	for (i = 0; i < nr_a2232; i++) {		zorro_release_device(zd_a2232[i]);	}	tty_unregister_driver(&a2232_driver);	tty_unregister_driver(&a2232_callout_driver);	free_irq(IRQ_AMIGA_VERTB, a2232_driver_ID);}#endif/***************************** End of Functions *********************/MODULE_AUTHOR("Enver Haase");MODULE_DESCRIPTION("Amiga A2232 multi-serial board driver");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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