Exemple #1
0
/**
 * uart_open() - Open the CG2900 UART for data transfers.
 * @dev:	Transport device information.
 *
 * Returns:
 *   0 if there is no error,
 *   -EACCES if write to transport failed,
 *   -EIO if chip did not answer to commands.
 */
static int uart_open(struct cg2900_trans_dev *dev)
{
	u8 data[HCI_BT_RESET_LEN + HCI_H4_SIZE];
	struct tty_struct *tty;
	int bytes_written;

	/*
	 * Chip has just been started up. It has a system to autodetect
	 * exact baud rate and transport to use. There are only a few commands
	 * it will recognize and HCI Reset is one of them.
	 * We therefore start with sending that before actually changing
	 * baud rate.
	 *
	 * Create the Hci_Reset packet
	 */
	data[0] = HCI_BT_CMD_H4_CHANNEL;
	data[1] = HCI_BT_RESET_CMD_LSB;
	data[2] = HCI_BT_RESET_CMD_MSB;
	data[3] = HCI_BT_RESET_PARAM_LEN;

	/* Get the TTY info and send the packet */
	tty = uart_info->tty;
	SET_BAUD_STATE(BAUD_SENDING_RESET);
	CG2900_DBG("Sending HCI reset before baud rate change");
	CG2900_DBG_DATA_CONTENT("HCI Reset", data, 4);
	bytes_written = tty->ops->write(tty, data,
					HCI_BT_RESET_LEN + HCI_H4_SIZE);
	if (bytes_written != HCI_BT_RESET_LEN + HCI_H4_SIZE) {
		CG2900_ERR("Only wrote %d bytes", bytes_written);
		SET_BAUD_STATE(BAUD_IDLE);
		return -EACCES;
	}

	/*
	 * Wait for command complete. If error, exit without changing
	 * baud rate.
	 */
	wait_event_interruptible_timeout(uart_wait_queue,
					BAUD_IDLE == uart_info->baud_rate_state,
					msecs_to_jiffies(UART_RESP_TIMEOUT));
	if (BAUD_IDLE != uart_info->baud_rate_state) {
		CG2900_ERR("Failed to send HCI Reset");
		SET_BAUD_STATE(BAUD_IDLE);
		return -EIO;
	}
 
#if 1	
	/* Just return if there will be no change of baud rate */
	if (uart_default_baud != uart_high_baud)	
		return set_baud_rate(uart_high_baud);
	else
		return 0;
#else
	return set_baud_rate(uart_high_baud);
#endif
}
Exemple #2
0
void pre_init(void) {
    morecore_area = core_buf;
    morecore_size = SERVER_CORE_SIZE;
    serial_lock();
    // Initialize the serial port
    set_dlab(0); // we always assume the dlab is 0 unless we explicitly change it
    disable_interrupt();
    disable_fifo();
    reset_lcr();
    reset_mcr();
    clear_iir();
    set_baud_rate(BAUD_RATE);
    reset_state();
    enable_fifo();
    enable_interrupt();
    clear_iir();
    // all done
    init_colours();
    /* query what getchar clients exist */
    num_getchar_clients = getchar_num_badges();
    getchar_clients = calloc(num_getchar_clients, sizeof(getchar_client_t));
    for (int i = 0; i < num_getchar_clients; i++) {
        unsigned int badge = getchar_enumerate_badge(i);
        assert(badge <= num_getchar_clients);
        getchar_clients[badge].client_id = badge;
        getchar_clients[badge].buf = getchar_buf(badge);
        getchar_clients[badge].last_head = -1;
    }
    set_putchar(serial_putchar);
    serial_irq_reg_callback(serial_irq, 0);
    /* Start regular heartbeat of 500ms */
    timeout_periodic(0, 500000000);
    serial_unlock();
}
        bool init(void)
        {
    		LPC_GPIO1->FIODIR &= ~(1<<9);


        	LPC_I2C2->I2MASK0 = 0x1F;
        	LPC_I2C2->I2CONSET = 0x40;
        	LPC_SC->PCONP |= (1<<25);

        	//Peripheral clock select
        	LPC_SC->PCLKSEL1 &= ~(3<<18);
        	LPC_SC->PCLKSEL1 |= (1<<18);

        	//Selecting TXD3, RXD3
        	LPC_PINCON->PINSEL9 &= ~((3<<24)|(3<<26));
        	LPC_PINCON->PINSEL9 |= ((3<<24)|(3<<26));

        	//set DLM and DLL for desired baudrate
        	set_baud_rate(9600);

        	//Enable Interrupt for UART3
        	enable_interrupt();

        	return true;
        }
Exemple #4
0
void usart_init(void)
{
    USART_TypeDef* const usart = USART2;
    uint32_t val;

    // enable peripheral clock
    enable_usart_clock(usart);

    // disable the uart
    usart->CR1 &= ~USART_CR1_UE;

    // set CR1
    val = usart->CR1;
    val &= ~(USART_CR1_SBK | USART_CR1_RWU | USART_CR1_IDLEIE | USART_CR1_RXNEIE |\
        USART_CR1_TCIE | USART_CR1_TXEIE | USART_CR1_PEIE | USART_CR1_PS | USART_CR1_PCE |\
        USART_CR1_WAKE | USART_CR1_M | USART_CR1_UE | USART_CR1_OVER8);
    val |= (USART_CR1_RE | USART_CR1_TE);
    usart->CR1= val;

    // set CR2
    val = usart->CR2;
    val &= ~(USART_CR2_ADD | USART_CR2_LBDL | USART_CR2_LBDIE | USART_CR2_LBCL |\
        USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | USART_CR2_STOP |\
        USART_CR2_LINEN);
    usart->CR2= val;

    // set CR3
    val = usart->CR3;
    val &= ~(USART_CR3_EIE | USART_CR3_IREN | USART_CR3_IRLP | USART_CR3_HDSEL |\
        USART_CR3_NACK | USART_CR3_SCEN | USART_CR3_DMAR | USART_CR3_DMAT |\
        USART_CR3_RTSE | USART_CR3_CTSE | USART_CR3_CTSIE | USART_CR3_ONEBIT);
    usart->CR3= val;

    // clear the status register
    val = usart->SR;
    val &= ~(USART_SR_PE | USART_SR_FE | USART_SR_NE | USART_SR_ORE | USART_SR_IDLE |\
        USART_SR_RXNE | USART_SR_TC | USART_SR_TXE | USART_SR_LBD | USART_SR_CTS);
    usart->SR= val;

    set_baud_rate(usart, 115200);

    // GTPR - no changes
    val = usart->GTPR;
    usart->GTPR = val;

#ifndef SERIAL_POLLED
    rx_wr = rx_rd = tx_wr = tx_rd = 0;
    rx_errors = 0;
    // enable the rx not empty interrupt
    usart->CR1 |= USART_CR1_RXNEIE;
    // enable USART2 interrupt
    HAL_NVIC_SetPriority(USART2_IRQn, 10, 0);
    NVIC_EnableIRQ(USART2_IRQn);
#endif

    // enable the uart
    usart->CR1 |= USART_CR1_UE;
}
Exemple #5
0
static void usart_hw_init(USART_t *ptr)
{
    USART_TypeDef* usart = ptr->usart;
    uint32_t val;

    // enable peripheral clock
    enable_usart_clock(usart);

    // disable the uart
    usart->CR1 &= ~USART_CR1_UE;

    // set CR1
    val = usart->CR1;
    val &= ~(USART_CR1_SBK | USART_CR1_RWU | USART_CR1_IDLEIE | USART_CR1_RXNEIE |\
        USART_CR1_TCIE | USART_CR1_TXEIE | USART_CR1_PEIE | USART_CR1_PS | USART_CR1_PCE |\
        USART_CR1_WAKE | USART_CR1_M | USART_CR1_UE | USART_CR1_OVER8);
    val |= (USART_CR1_RE | USART_CR1_TE);
    usart->CR1= val;

    // set CR2
    val = usart->CR2;
    val &= ~(USART_CR2_ADD | USART_CR2_LBDL | USART_CR2_LBDIE | USART_CR2_LBCL |\
        USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | USART_CR2_STOP |\
        USART_CR2_LINEN);
    usart->CR2= val;

    // set CR3
    val = usart->CR3;
    val &= ~(USART_CR3_EIE | USART_CR3_IREN | USART_CR3_IRLP | USART_CR3_HDSEL |\
        USART_CR3_NACK | USART_CR3_SCEN | USART_CR3_DMAR | USART_CR3_DMAT |\
        USART_CR3_RTSE | USART_CR3_CTSE | USART_CR3_CTSIE | USART_CR3_ONEBIT);
    usart->CR3= val;

    // clear the status register
    val = usart->SR;
    val &= ~(USART_SR_RXNE | USART_SR_TC | USART_SR_LBD | USART_SR_CTS);
    usart->SR= val;

    set_baud_rate(usart, 115200);

    // GTPR - no changes
    val = usart->GTPR;
    usart->GTPR = val;

#ifndef USART_POLLED
    // turn on interrupts
    usart->CR1 |= USART_CR1_RXNEIE;
    HAL_NVIC_SetPriority(ptr->irq, 10, 0);
    NVIC_EnableIRQ(ptr->irq);
#endif

    // enable the uart
    usart->CR1 |= USART_CR1_UE;
}
serial::err
serial_port_x86::open(void)
{
    disable_interrupt_mode();

    set_baud_rate(m_baud);
    set_parity_mode(m_parity);
    set_data_size(m_data_size);
    set_stop_bits(m_stop_bits);
    enable_fifo();

    enable_interrupt_mode(m_interrupt_mode);

    return serial::success;
}
Exemple #7
0
void serial_init(long baud)
{
  set_baud_rate(baud);
  
  /* baud doubler off  - Only needed on Uno XXX */
  UCSR0A &= ~(1 << U2X0);
          
  // enable rx and tx
  UCSR0B |= 1<<RXEN0;
  UCSR0B |= 1<<TXEN0;
	
  // enable interrupt on complete reception of a byte
  UCSR0B |= 1<<RXCIE0;
	  
  // defaults to 8-bit, no parity, 1 stop bit
}
Exemple #8
0
void serial_init() {
  set_baud_rate(BAUD_RATE);
  
	/* baud doubler off  - Only needed on Uno XXX */
  UCSR0A &= ~(1 << U2X0);
          
	// enable rx and tx
  UCSR0B |= 1<<RXEN0;
  UCSR0B |= 1<<TXEN0;
	
	// enable interrupt on complete reception of a byte
  UCSR0B |= 1<<RXCIE0;
	  
	// defaults to 8-bit, no parity, 1 stop bit
	
  printPgmString(PSTR("# LasaurGrbl " LASAURGRBL_VERSION));
  printPgmString(PSTR("\n"));
}
Exemple #9
0
void serial_init(gdb_state_t *gdb) {
    // Initialize the serial port
    int UNUSED error;
    error = serial_lock();
    gdb_state = gdb;
    set_dlab(0); // we always assume the dlab is 0 unless we explicitly change it
    disable_interrupt();
    disable_fifo();
    reset_lcr();
    reset_mcr();
    clear_iir();
    set_baud_rate(BAUD_RATE);
    reset_state();
    enable_fifo();
    enable_interrupt();
    clear_iir();
    initialise_buffer();
    error = serial_unlock();

}
Exemple #10
0
void main(void) {
  /* put your own code here */
  	EnableInterrupts;
    
  	DDR1AD0 =	DDRT	= 0xFF;	
	PT1AD0	= 	PTT		= 0x00;
	
	set_baud_rate(9600);
		 
	send();	
	fct_set(8,2,58);
	disp_on(1,1,1);
	entry_mode(1,0);	
	clear_disp();

	char  val,buf[16] ;
	
#define go 5000
	while(1)
	{
		memset(buf,0,16);
		for(int v=0,i =0; i<16 ; i++)
		{   v=0;
			while(	chk_rx() >= 0	? 0:
					i==0 			? 1:
					v++ < go		? 1:
					0);
			if (v >= go){	break;	}
			buf[i]=fetch_char();				
		}
		return_home();
		clear_disp();
		prt_str(buf);	
	}
	 
  for(;;) {
    _FEED_COP(); /* feeds the dog */
  } /* loop forever */
  /* please make sure that you never leave main */
}
Exemple #11
0
static void uart_setup(void)
{
  /* #define CONFIG_FOSC (F_CPU * 2) */
  /* const uint16_t x = CONFIG_FOSC / (16 * BAUDS) - 1; */
#if 0 /* (bauds == 9600) */
  const uint16_t x = 206;
#elif 0 /* (bauds == 115200) */
  const uint16_t x = 16;
#elif 0 /* (bauds == 500000) */
  const uint16_t x = 3;
#elif 0 /* (bauds == 1000000) */
  const uint16_t x = 1;
#endif

  set_baud_rate(9600);

  /* baud doubler off  - Only needed on Uno XXX */
  UCSR0A &= ~(1 << U2X0);

  UCSR0B = 1 << TXEN0;

  /* default to 8n1 framing */
  UCSR0C = (3 << 1);
}
Exemple #12
0
int SLang_init_tty (int abort_char, int no_flow_control, int opost)
{
   TTY_Termio_Type newtty;

   SLsig_block_signals ();

   if (TTY_Inited)
     {
	SLsig_unblock_signals ();
	return 0;
     }

   TTY_Open = 0;
   SLKeyBoard_Quit = 0;

   if ((SLang_TT_Read_FD == -1)
       || (1 != isatty (SLang_TT_Read_FD)))
     {
#ifdef O_RDWR
# if !defined(__BEOS__) && !defined(__APPLE__)
	/* I have been told that BEOS will HANG if passed /dev/tty */
	if ((SLang_TT_Read_FD = open("/dev/tty", O_RDWR)) >= 0)
	  {
#  ifdef FD_CLOEXEC
	     /* Make sure /dev/tty is closed upon exec */
	     int flags = fcntl (SLang_TT_Read_FD, F_GETFD);
	     if (flags >= 0)
	       (void) fcntl(SLang_TT_Read_FD, F_SETFD, flags | FD_CLOEXEC);
#  endif
	     TTY_Open = 1;
	  }
# endif
#endif
	if (TTY_Open == 0)
	  {
	     SLang_TT_Read_FD = fileno (stderr);
	     if (1 != isatty (SLang_TT_Read_FD))
	       {
		  SLang_TT_Read_FD = fileno (stdin);
		  if (1 != isatty (SLang_TT_Read_FD))
		    {
		       fprintf (stderr, "Failed to open terminal.");
		       return -1;
		    }
	       }
	  }
     }

   SLang_Abort_Char = abort_char;

   /* Some systems may not permit signals to be blocked.  As a result, the
    * return code must be checked.
    */
   while (-1 == GET_TERMIOS(SLang_TT_Read_FD, &Old_TTY))
     {
	if (errno != EINTR)
	  {
	     SLsig_unblock_signals ();
	     return -1;
	  }
     }

   while (-1 == GET_TERMIOS(SLang_TT_Read_FD, &newtty))
     {
	if (errno != EINTR)
	  {
	     SLsig_unblock_signals ();
	     return -1;
	  }
     }

#ifndef HAVE_TERMIOS_H
   (void) opost;
   (void) no_flow_control;
   newtty.s.sg_flags &= ~(ECHO);
   newtty.s.sg_flags &= ~(CRMOD);
   /*   if (Flow_Control == 0) newtty.s.sg_flags &= ~IXON; */
   newtty.t.t_eofc = 1;
   if (abort_char == -1) SLang_Abort_Char = newtty.t.t_intrc;
   newtty.t.t_intrc = SLang_Abort_Char;	/* ^G */
   newtty.t.t_quitc = 255;
   newtty.lt.t_suspc = 255;   /* to ignore ^Z */
   newtty.lt.t_dsuspc = 255;    /* to ignore ^Y */
   newtty.lt.t_lnextc = 255;
   newtty.s.sg_flags |= CBREAK;		/* do I want cbreak or raw????? */
#else

   /* get baud rate */

   newtty.c_iflag &= ~(ECHO | INLCR | ICRNL);
#ifdef ISTRIP
   /* newtty.c_iflag &= ~ISTRIP; */
#endif
   if (opost == 0) newtty.c_oflag &= ~OPOST;

   set_baud_rate (&newtty);

   if (no_flow_control) newtty.c_iflag &= ~IXON; else newtty.c_iflag |= IXON;

   newtty.c_cc[VEOF] = 1;
   newtty.c_cc[VMIN] = 1;
   newtty.c_cc[VTIME] = 0;
   newtty.c_lflag = ISIG | NOFLSH;
   if (abort_char == -1) SLang_Abort_Char = newtty.c_cc[VINTR];
   newtty.c_cc[VINTR] = SLang_Abort_Char;   /* ^G */
   newtty.c_cc[VQUIT] = NULL_VALUE;
   newtty.c_cc[VSUSP] = NULL_VALUE;   /* to ignore ^Z */
#ifdef VDSUSP
   newtty.c_cc[VDSUSP] = NULL_VALUE;   /* to ignore ^Y */
#endif
#ifdef VLNEXT
   newtty.c_cc[VLNEXT] = NULL_VALUE;   /* to ignore ^V ? */
#endif
#ifdef VSWTCH
   newtty.c_cc[VSWTCH] = NULL_VALUE;   /* to ignore who knows what */
#endif
#endif /* NOT HAVE_TERMIOS_H */

   while (-1 == SET_TERMIOS(SLang_TT_Read_FD, &newtty))
     {
	if (errno != EINTR)
	  {
	     SLsig_unblock_signals ();
	     return -1;
	  }
     }

   TTY_Inited = 1;
   SLsig_unblock_signals ();
   return 0;
}
Exemple #13
0
/* Function to configure the UART
 * on receiving a notification from the ST KIM driver to install the line
 * discipline, this function does UART configuration necessary for the STK
 */
int st_uart_config(unsigned char install)
{
	int ldisc, len, fd, flow_ctrl;
	unsigned char buf[UART_DEV_NAME_LEN];
	uim_speed_change_cmd cmd;
	char uart_dev_name[UART_DEV_NAME_LEN];
	long cust_baud_rate;

	uim_bdaddr_change_cmd addr_cmd;

	UIM_START_FUNC();

	if (install == '1') {
		memset(buf, 0, UART_DEV_NAME_LEN);
		fd = open(DEV_NAME_SYSFS, O_RDONLY);
		if (fd < 0) {
			UIM_ERR("Can't open %s", DEV_NAME_SYSFS);
			return -1;
		}
		len = read(fd, buf, UART_DEV_NAME_LEN);
		if (len < 0) {
			UIM_ERR("read err (%s)", strerror(errno));
			close(fd);
			return len;
		}
		sscanf((const char*)buf, "%s", uart_dev_name);
		close(fd);

		memset(buf, 0, UART_DEV_NAME_LEN);
		fd = open(BAUD_RATE_SYSFS, O_RDONLY);
		if (fd < 0) {
			UIM_ERR("Can't open %s", BAUD_RATE_SYSFS);
			return -1;
		}
		len = read(fd, buf, UART_DEV_NAME_LEN);
		if (len < 0) {
			UIM_ERR("read err (%s)", strerror(errno));
			close(fd);
			return len;
		}
		close(fd);
		sscanf((const char*)buf, "%ld", &cust_baud_rate);

		memset(buf, 0, UART_DEV_NAME_LEN);
		fd = open(FLOW_CTRL_SYSFS, O_RDONLY);
		if (fd < 0) {
			UIM_ERR("Can't open %s", FLOW_CTRL_SYSFS);
			close(fd);
			return -1;
		}
		len = read(fd, buf, UART_DEV_NAME_LEN);
		if (len < 0) {
			UIM_ERR("read err (%s)", strerror(errno));
			close(fd);
			return len;
		}
		close(fd);
		sscanf((const char*)buf, "%d", &flow_ctrl);

		UIM_VER(" signal received, opening %s", uart_dev_name);

		dev_fd = open(uart_dev_name, O_RDWR);
		if (dev_fd < 0) {
			UIM_ERR("Can't open %s", uart_dev_name);
			return -1;
		}

		/*
		 * Set only the default baud rate.
		 * This will set the baud rate to default 115200
		 */
		if (set_baud_rate(dev_fd) < 0) {
			UIM_ERR("set_baudrate() failed");
			close(dev_fd);
			return -1;
		}

		fcntl(dev_fd, F_SETFL,fcntl(dev_fd, F_GETFL) | O_NONBLOCK);
		/* Set only the custom baud rate */
		if (cust_baud_rate != 115200) {

			UIM_VER("Setting speed to %ld", cust_baud_rate);
			/* Forming the packet for Change speed command */
			cmd.uart_prefix = HCI_COMMAND_PKT;
			cmd.hci_hdr.opcode = HCI_HDR_OPCODE;
			cmd.hci_hdr.plen = sizeof(unsigned long);
			cmd.speed = cust_baud_rate;

			/* Writing the change speed command to the UART
			 * This will change the UART speed at the controller
			 * side
			 */
			len = write(dev_fd, &cmd, sizeof(cmd));
			if (len < 0) {
				UIM_ERR("Failed to write speed-set command");
				close(dev_fd);
				return -1;
			}

			/* Read the response for the Change speed command */
			if (read_command_complete(dev_fd, HCI_HDR_OPCODE) < 0) {
				close(dev_fd);
				return -1;
			}

			UIM_VER("Speed changing to %ld, %d", cust_baud_rate, flow_ctrl);
			/* Set the actual custom baud rate at the host side */
			if (set_custom_baud_rate(dev_fd, cust_baud_rate, flow_ctrl) < 0) {
				UIM_ERR("set_custom_baud_rate() failed");
				close(dev_fd);
				return -1;
			}

			/* Set the uim BD address */
			if (uim_bd_address[0] != 0) {

				memset(&addr_cmd, 0, sizeof(addr_cmd));
				/* Forming the packet for change BD address command*/
				addr_cmd.uart_prefix = HCI_COMMAND_PKT;
				addr_cmd.hci_hdr.opcode = WRITE_BD_ADDR_OPCODE;
				addr_cmd.hci_hdr.plen = sizeof(bdaddr_t);
				memcpy(&addr_cmd.addr, bd_addr, sizeof(bdaddr_t));

				/* Writing the change BD address command to the UART
				 * This will change the change BD address  at the controller
				 * side
				 */
				len = write(dev_fd, &addr_cmd, sizeof(addr_cmd));
				if (len < 0) {
					UIM_ERR("Failed to write BD address command");
					close(dev_fd);
					return -1;
				}

				/* Read the response for the change BD address command */
				if (read_command_complete(dev_fd, WRITE_BD_ADDR_OPCODE) < 0) {
					close(dev_fd);
					return -1;
				}
				UIM_VER("BD address changed to %s", uim_bd_address);
			}
#ifdef UIM_DEBUG
			read_firmware_version(dev_fd);
#endif
		}

		/* After the UART speed has been changed, the IOCTL is
		 * is called to set the line discipline to N_TI_WL
		 */
		ldisc = N_TI_WL;
		if (ioctl(dev_fd, TIOCSETD, &ldisc) < 0) {
			UIM_ERR(" Can't set line discipline");
			close(dev_fd);
			return -1;
		}
		UIM_DBG("Installed N_TI_WL Line displine");
	}
	else {
		UIM_DBG("Un-Installed N_TI_WL Line displine");
		/* UNINSTALL_N_TI_WL - When the Signal is received from KIM */
		/* closing UART fd */
		close(dev_fd);
	}
	return 0;
}
Exemple #14
0
/******************************************************************
 *		COMM_DeviceIoControl
 *
 *
 */
NTSTATUS COMM_DeviceIoControl(HANDLE hDevice, 
                              HANDLE hEvent, PIO_APC_ROUTINE UserApcRoutine,
                              PVOID UserApcContext, 
                              PIO_STATUS_BLOCK piosb, 
                              ULONG dwIoControlCode,
                              LPVOID lpInBuffer, DWORD nInBufferSize,
                              LPVOID lpOutBuffer, DWORD nOutBufferSize)
{
    DWORD       sz = 0, access = FILE_READ_DATA;
    NTSTATUS    status = STATUS_SUCCESS;
    int         fd = -1;

    TRACE("%p %s %p %ld %p %ld %p\n",
          hDevice, iocode2str(dwIoControlCode), lpInBuffer, nInBufferSize,
          lpOutBuffer, nOutBufferSize, piosb);

    piosb->Information = 0;

    if (dwIoControlCode != IOCTL_SERIAL_GET_TIMEOUTS)
        if ((status = wine_server_handle_to_fd( hDevice, access, &fd, NULL )))
            goto error;

    switch (dwIoControlCode)
    {
    case IOCTL_SERIAL_CLR_DTR:
#ifdef TIOCM_DTR
        if (whack_modem(fd, ~TIOCM_DTR, 0) == -1) status = FILE_GetNtStatus();
#else
        status = STATUS_NOT_SUPPORTED;
#endif
        break;
    case IOCTL_SERIAL_CLR_RTS:
#ifdef TIOCM_RTS
        if (whack_modem(fd, ~TIOCM_RTS, 0) == -1) status = FILE_GetNtStatus();
#else
        status = STATUS_NOT_SUPPORTED;
#endif
        break;
    case IOCTL_SERIAL_GET_BAUD_RATE:
        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_BAUD_RATE))
        {
            if (!(status = get_baud_rate(fd, (SERIAL_BAUD_RATE*)lpOutBuffer)))
                sz = sizeof(SERIAL_BAUD_RATE);
        }
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_GET_CHARS:
        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_CHARS))
        {
            if (!(status = get_special_chars(fd, (SERIAL_CHARS*)lpOutBuffer)))
                sz = sizeof(SERIAL_CHARS);
        }
        else
            status = STATUS_INVALID_PARAMETER;
        break;
     case IOCTL_SERIAL_GET_COMMSTATUS:
        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_STATUS))
        {
            if (!(status = get_status(fd, (SERIAL_STATUS*)lpOutBuffer)))
                sz = sizeof(SERIAL_STATUS);
        }
        else status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_GET_HANDFLOW:
        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_HANDFLOW))
        {
            if (!(status = get_hand_flow(fd, (SERIAL_HANDFLOW*)lpOutBuffer)))
                sz = sizeof(SERIAL_HANDFLOW);
        }
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_GET_LINE_CONTROL:
        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_LINE_CONTROL))
        {
            if (!(status = get_line_control(fd, (SERIAL_LINE_CONTROL*)lpOutBuffer)))
                sz = sizeof(SERIAL_LINE_CONTROL);
        }
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_GET_MODEMSTATUS:
        if (lpOutBuffer && nOutBufferSize == sizeof(DWORD))
        {
            if (!(status = get_modem_status(fd, (DWORD*)lpOutBuffer)))
                sz = sizeof(DWORD);
        }
        else status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_GET_TIMEOUTS:
        if (lpOutBuffer && nOutBufferSize == sizeof(SERIAL_TIMEOUTS))
        {
            if (!(status = get_timeouts(hDevice, (SERIAL_TIMEOUTS*)lpOutBuffer)))
                sz = sizeof(SERIAL_TIMEOUTS);
        }
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_GET_WAIT_MASK:
        if (lpOutBuffer && nOutBufferSize == sizeof(DWORD))
        {
            if (!(status = get_wait_mask(hDevice, (DWORD*)lpOutBuffer)))
                sz = sizeof(DWORD);
        }
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_IMMEDIATE_CHAR:
        if (lpInBuffer && nInBufferSize == sizeof(CHAR))
            status = xmit_immediate(hDevice, fd, lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_PURGE:
        if (lpInBuffer && nInBufferSize == sizeof(DWORD))
            status = purge(fd, *(DWORD*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_RESET_DEVICE:
        FIXME("Unsupported\n");
        break;
    case IOCTL_SERIAL_SET_BAUD_RATE:
        if (lpInBuffer && nInBufferSize == sizeof(SERIAL_BAUD_RATE))
            status = set_baud_rate(fd, (const SERIAL_BAUD_RATE*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_BREAK_OFF:
#if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
	if (ioctl(fd, TIOCCBRK, 0) == -1)
        {
            TRACE("ioctl failed\n");
            status = FILE_GetNtStatus();
        }
#else
	FIXME("ioctl not available\n");
	status = STATUS_NOT_SUPPORTED;
#endif
        break;
    case IOCTL_SERIAL_SET_BREAK_ON:
#if defined(TIOCSBRK) && defined(TIOCCBRK) /* check if available for compilation */
	if (ioctl(fd, TIOCSBRK, 0) == -1)
        {
            TRACE("ioctl failed\n");
            status = FILE_GetNtStatus();
        }
#else
	FIXME("ioctl not available\n");
	status = STATUS_NOT_SUPPORTED;
#endif
        break;
    case IOCTL_SERIAL_SET_CHARS:
        if (lpInBuffer && nInBufferSize == sizeof(SERIAL_CHARS))
            status = set_special_chars(fd, (const SERIAL_CHARS*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_DTR:
#ifdef TIOCM_DTR
        if (whack_modem(fd, 0, TIOCM_DTR) == -1) status = FILE_GetNtStatus();
#else
        status = STATUS_NOT_SUPPORTED;
#endif
        break;
    case IOCTL_SERIAL_SET_HANDFLOW:
        if (lpInBuffer && nInBufferSize == sizeof(SERIAL_HANDFLOW))
            status = set_handflow(fd, (const SERIAL_HANDFLOW*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_LINE_CONTROL:
        if (lpInBuffer && nInBufferSize == sizeof(SERIAL_LINE_CONTROL))
            status = set_line_control(fd, (const SERIAL_LINE_CONTROL*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_QUEUE_SIZE:
        if (lpInBuffer && nInBufferSize == sizeof(SERIAL_QUEUE_SIZE))
            status = set_queue_size(fd, (const SERIAL_QUEUE_SIZE*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_RTS:
#ifdef TIOCM_RTS
        if (whack_modem(fd, 0, TIOCM_RTS) == -1) status = FILE_GetNtStatus();
#else
        status = STATUS_NOT_SUPPORTED;
#endif
        break;
    case IOCTL_SERIAL_SET_TIMEOUTS:
        if (lpInBuffer && nInBufferSize == sizeof(SERIAL_TIMEOUTS))
            status = set_timeouts(hDevice, fd, (const SERIAL_TIMEOUTS*)lpInBuffer);
        else
            status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_WAIT_MASK:
        if (lpInBuffer && nInBufferSize == sizeof(DWORD))
        {
            status = set_wait_mask(hDevice, *(DWORD*)lpInBuffer);
        }
        else status = STATUS_INVALID_PARAMETER;
        break;
    case IOCTL_SERIAL_SET_XOFF:
        status = set_XOff(fd);
        break;
    case IOCTL_SERIAL_SET_XON:
        status = set_XOn(fd);
        break;
    default:
        FIXME("Unsupported IOCTL %lx (type=%lx access=%lx func=%lx meth=%lx)\n", 
              dwIoControlCode, dwIoControlCode >> 16, (dwIoControlCode >> 14) & 3,
              (dwIoControlCode >> 2) & 0xFFF, dwIoControlCode & 3);
        sz = 0;
        status = STATUS_INVALID_PARAMETER;
        break;
    }
    if (fd != -1) wine_server_release_fd( hDevice, fd );
 error:
    piosb->u.Status = status;
    piosb->Information = sz;
    if (hEvent) NtSetEvent(hEvent, NULL);
    return status;
}