sdla_chdlc.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:129k
-
- return chdlc_configure(card, &cfg);
- }
- /*-----------------------------------------------------------------------------
- set_asy_config() used to set asynchronous configuration options on the board
- ------------------------------------------------------------------------------*/
- static int set_asy_config(sdla_t* card)
- {
- ASY_CONFIGURATION_STRUCT cfg;
- CHDLC_MAILBOX_STRUCT *mailbox = card->mbox;
- int err;
- memset(&cfg, 0, sizeof(ASY_CONFIGURATION_STRUCT));
- if(card->wandev.clocking)
- cfg.baud_rate = card->wandev.bps;
- cfg.line_config_options = (card->wandev.interface == WANOPT_RS232) ?
- INTERFACE_LEVEL_RS232 : INTERFACE_LEVEL_V35;
- cfg.modem_config_options = 0;
- cfg.asy_API_options = card->u.c.api_options;
- cfg.asy_protocol_options = card->u.c.protocol_options;
- cfg.Tx_bits_per_char = card->u.c.tx_bits_per_char;
- cfg.Rx_bits_per_char = card->u.c.rx_bits_per_char;
- cfg.stop_bits = card->u.c.stop_bits;
- cfg.parity = card->u.c.parity;
- cfg.break_timer = card->u.c.break_timer;
- cfg.asy_Rx_inter_char_timer = card->u.c.inter_char_timer;
- cfg.asy_Rx_complete_length = card->u.c.rx_complete_length;
- cfg.XON_char = card->u.c.xon_char;
- cfg.XOFF_char = card->u.c.xoff_char;
- cfg.asy_statistics_options = (CHDLC_TX_DATA_BYTE_COUNT_STAT |
- CHDLC_RX_DATA_BYTE_COUNT_STAT);
- mailbox->buffer_length = sizeof(ASY_CONFIGURATION_STRUCT);
- memcpy(mailbox->data, &cfg, mailbox->buffer_length);
- mailbox->command = SET_ASY_CONFIGURATION;
- err = sdla_exec(mailbox) ? mailbox->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error (card, err, mailbox);
- return err;
- }
- /*============================================================================
- * Enable asynchronous communications.
- */
- static int asy_comm_enable (sdla_t* card)
- {
- int err;
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- mb->buffer_length = 0;
- mb->command = ENABLE_ASY_COMMUNICATIONS;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK && card->wandev.dev)
- chdlc_error(card, err, mb);
-
- if (!err)
- card->u.c.comm_enabled = 1;
- return err;
- }
- /*============================================================================
- * Process global exception condition
- */
- static int process_global_exception(sdla_t *card)
- {
- CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
- int err;
- mbox->buffer_length = 0;
- mbox->command = READ_GLOBAL_EXCEPTION_CONDITION;
- err = sdla_exec(mbox) ? mbox->return_code : CMD_TIMEOUT;
- if(err != CMD_TIMEOUT ){
-
- switch(mbox->return_code) {
-
- case EXCEP_MODEM_STATUS_CHANGE:
- printk(KERN_INFO "%s: Modem status changen",
- card->devname);
- switch(mbox->data[0] & (DCD_HIGH | CTS_HIGH)) {
- case (DCD_HIGH):
- printk(KERN_INFO "%s: DCD high, CTS lown",card->devname);
- break;
- case (CTS_HIGH):
- printk(KERN_INFO "%s: DCD low, CTS highn",card->devname);
- break;
- case ((DCD_HIGH | CTS_HIGH)):
- printk(KERN_INFO "%s: DCD high, CTS highn",card->devname);
- break;
- default:
- printk(KERN_INFO "%s: DCD low, CTS lown",card->devname);
- break;
- }
- break;
- case EXCEP_TRC_DISABLED:
- printk(KERN_INFO "%s: Line trace disabledn",
- card->devname);
- break;
- case EXCEP_IRQ_TIMEOUT:
- printk(KERN_INFO "%s: IRQ timeout occurredn",
- card->devname);
- break;
- case 0x17:
- if (card->tty_opt){
- if (card->tty && card->tty_open){
- printk(KERN_INFO
- "%s: Modem Hangup Exception: Hanging Up!n",
- card->devname);
- tty_hangup(card->tty);
- }
- break;
- }
- /* If TTY is not used just drop throught */
-
- default:
- printk(KERN_INFO "%s: Global exception %xn",
- card->devname, mbox->return_code);
- break;
- }
- }
- return 0;
- }
- /*============================================================================
- * Process chdlc exception condition
- */
- static int process_chdlc_exception(sdla_t *card)
- {
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int err;
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_EXCEPTION_CONDITION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if(err != CMD_TIMEOUT) {
-
- switch (err) {
- case EXCEP_LINK_ACTIVE:
- port_set_state(card, WAN_CONNECTED);
- trigger_chdlc_poll(card->wandev.dev);
- break;
- case EXCEP_LINK_INACTIVE_MODEM:
- port_set_state(card, WAN_DISCONNECTED);
- unconfigure_ip(card);
- trigger_chdlc_poll(card->wandev.dev);
- break;
- case EXCEP_LINK_INACTIVE_KPALV:
- port_set_state(card, WAN_DISCONNECTED);
- printk(KERN_INFO "%s: Keepalive timer expired.n",
- card->devname);
- unconfigure_ip(card);
- trigger_chdlc_poll(card->wandev.dev);
- break;
- case EXCEP_IP_ADDRESS_DISCOVERED:
- if (configure_ip(card))
- return -1;
- break;
- case EXCEP_LOOPBACK_CONDITION:
- printk(KERN_INFO "%s: Loopback Condition Detected.n",
- card->devname);
- break;
- case NO_CHDLC_EXCEP_COND_TO_REPORT:
- printk(KERN_INFO "%s: No exceptions reported.n",
- card->devname);
- break;
- }
- }
- return 0;
- }
- /*============================================================================
- * Configure IP from SLARP negotiation
- * This adds dynamic routes when SLARP has provided valid addresses
- */
- static int configure_ip (sdla_t* card)
- {
- netdevice_t *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area;
- char err;
- if (!dev)
- return 0;
- chdlc_priv_area = dev->priv;
-
-
- /* set to discover */
- if(card->u.c.slarp_timer != 0x00) {
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_CONFIGURATION_STRUCT *cfg;
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
-
- if(err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- return -1;
- }
- cfg = (CHDLC_CONFIGURATION_STRUCT *)mb->data;
- chdlc_priv_area->IP_address = cfg->IP_address;
- chdlc_priv_area->IP_netmask = cfg->IP_netmask;
- /* Set flag to add route */
- chdlc_priv_area->route_status = ADD_ROUTE;
- /* The idea here is to add the route in the poll routine.
- This way, we aren't in interrupt context when adding routes */
- trigger_chdlc_poll(dev);
- }
- return 0;
- }
- /*============================================================================
- * Un-Configure IP negotiated by SLARP
- * This removes dynamic routes when the link becomes inactive.
- */
- static int unconfigure_ip (sdla_t* card)
- {
- netdevice_t *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area;
- if (!dev)
- return 0;
- chdlc_priv_area= dev->priv;
-
- if (chdlc_priv_area->route_status == ROUTE_ADDED) {
- /* Note: If this function is called, the
- * port state has been DISCONNECTED. This state
- * change will trigger a poll_disconnected
- * function, that will check for this condition.
- */
- chdlc_priv_area->route_status = REMOVE_ROUTE;
- }
- return 0;
- }
- /*============================================================================
- * Routine to add/remove routes
- * Called like a polling routine when Routes are flagged to be added/removed.
- */
- static void process_route (sdla_t *card)
- {
- netdevice_t *dev = card->wandev.dev;
- unsigned char port_num;
- chdlc_private_area_t *chdlc_priv_area = NULL;
- u32 local_IP_addr = 0;
- u32 remote_IP_addr = 0;
- u32 IP_netmask, IP_addr;
- int err = 0;
- #if defined(LINUX_2_1) || defined(LINUX_2_4)
- struct in_device *in_dev;
- mm_segment_t fs;
- struct ifreq if_info;
- struct sockaddr_in *if_data1, *if_data2;
- #else
- unsigned long fs = 0;
- struct rtentry route;
- #endif
-
- chdlc_priv_area = dev->priv;
- port_num = card->u.c.comm_port;
- /* Bug Fix Mar 16 2000
- * AND the IP address to the Mask before checking
- * the last two bits. */
- if((chdlc_priv_area->route_status == ADD_ROUTE) &&
- ((chdlc_priv_area->IP_address & ~chdlc_priv_area->IP_netmask) > 2)) {
- printk(KERN_INFO "%s: Dynamic route failure.n",card->devname);
- if(card->u.c.slarp_timer) {
- u32 addr_net = htonl(chdlc_priv_area->IP_address);
- printk(KERN_INFO "%s: Bad IP address %u.%u.%u.%u receivedn",
- card->devname,
- NIPQUAD(addr_net));
- printk(KERN_INFO "%s: from remote station.n",
- card->devname);
- }else{
- u32 addr_net = htonl(chdlc_priv_area->IP_address);
- printk(KERN_INFO "%s: Bad IP address %u.%u.%u.%u issuedn",
- card->devname,
- NIPQUAD(addr_net));
- printk(KERN_INFO "%s: to remote station. Localn",
- card->devname);
- printk(KERN_INFO "%s: IP address must be A.B.C.1n",
- card->devname);
- printk(KERN_INFO "%s: or A.B.C.2.n",card->devname);
- }
- /* remove the route due to the IP address error condition */
- chdlc_priv_area->route_status = REMOVE_ROUTE;
- err = 1;
- }
- /* If we are removing a route with bad IP addressing, then use the */
- /* locally configured IP addresses */
- if((chdlc_priv_area->route_status == REMOVE_ROUTE) && err) {
- /* do not remove a bad route that has already been removed */
- if(chdlc_priv_area->route_removed) {
- return;
- }
- #if defined(LINUX_2_1) || defined(LINUX_2_4)
- in_dev = dev->ip_ptr;
- if(in_dev != NULL) {
- struct in_ifaddr *ifa = in_dev->ifa_list;
- if (ifa != NULL ) {
- local_IP_addr = ifa->ifa_local;
- IP_netmask = ifa->ifa_mask;
- }
- }
- #else
- local_IP_addr = dev->pa_addr;
- remote_IP_addr = dev->pa_dstaddr;
- IP_netmask = dev->pa_mask;
- #endif
- }else{
- /* According to Cisco HDLC, if the point-to-point address is
- A.B.C.1, then we are the opposite (A.B.C.2), and vice-versa.
- */
- IP_netmask = ntohl(chdlc_priv_area->IP_netmask);
- remote_IP_addr = ntohl(chdlc_priv_area->IP_address);
-
- /* If Netmask is 255.255.255.255 the local address
- * calculation will fail. Default it back to 255.255.255.0 */
- if (IP_netmask == 0xffffffff)
- IP_netmask &= 0x00ffffff;
- /* Bug Fix Mar 16 2000
- * AND the Remote IP address with IP netmask, instead
- * of static netmask of 255.255.255.0 */
- local_IP_addr = (remote_IP_addr & IP_netmask) +
- (~remote_IP_addr & ntohl(0x0003));
- if(!card->u.c.slarp_timer) {
- IP_addr = local_IP_addr;
- local_IP_addr = remote_IP_addr;
- remote_IP_addr = IP_addr;
- }
- }
- fs = get_fs(); /* Save file system */
- set_fs(get_ds()); /* Get user space block */
- #if defined(LINUX_2_1) || defined(LINUX_2_4)
- /* Setup a structure for adding/removing routes */
- memset(&if_info, 0, sizeof(if_info));
- strcpy(if_info.ifr_name, dev->name);
- #else
- /* Setup a structure for adding/removing routes */
- dev->pa_mask = IP_netmask;
- dev->pa_dstaddr = remote_IP_addr;
- dev->pa_addr = local_IP_addr;
- memset(&route, 0, sizeof(route));
- route.rt_dev = dev->name;
- route.rt_flags = 0;
- ((struct sockaddr_in *)&(route.rt_dst))->sin_addr.s_addr =
- dev->pa_dstaddr;
- ((struct sockaddr_in *)&(route.rt_dst))->sin_family = AF_INET;
- ((struct sockaddr_in *)&(route.rt_genmask))->sin_addr.s_addr =
- 0xFFFFFFFF;
- ((struct sockaddr_in *)&(route.rt_genmask))->sin_family =
- AF_INET;
- #endif
- switch (chdlc_priv_area->route_status) {
- case ADD_ROUTE:
- if(!card->u.c.slarp_timer) {
- #if defined(LINUX_2_1) || defined(LINUX_2_4)
- if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data2->sin_addr.s_addr = remote_IP_addr;
- if_data2->sin_family = AF_INET;
- err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
- #else
- err = ip_rt_new(&route);
- #endif
- } else {
- #if defined(LINUX_2_1) || defined(LINUX_2_4)
- if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
- if_data1->sin_addr.s_addr = local_IP_addr;
- if_data1->sin_family = AF_INET;
- if(!(err = devinet_ioctl(SIOCSIFADDR, &if_info))){
- if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data2->sin_addr.s_addr = remote_IP_addr;
- if_data2->sin_family = AF_INET;
- err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
- }
- #else
- err = ip_rt_new(&route);
- #endif
- }
- if(err) {
- printk(KERN_INFO "%s: Add route %u.%u.%u.%u failed (%d)n",
- card->devname, NIPQUAD(remote_IP_addr), err);
- } else {
- ((chdlc_private_area_t *)dev->priv)->route_status = ROUTE_ADDED;
- printk(KERN_INFO "%s: Dynamic route added.n",
- card->devname);
- printk(KERN_INFO "%s: Local IP addr : %u.%u.%u.%un",
- card->devname, NIPQUAD(local_IP_addr));
- printk(KERN_INFO "%s: Remote IP addr: %u.%u.%u.%un",
- card->devname, NIPQUAD(remote_IP_addr));
- chdlc_priv_area->route_removed = 0;
- }
- break;
- case REMOVE_ROUTE:
-
- #if defined(LINUX_2_1) || defined(LINUX_2_4)
- /* Change the local ip address of the interface to 0.
- * This will also delete the destination route.
- */
- if(!card->u.c.slarp_timer) {
- if_data2 = (struct sockaddr_in *)&if_info.ifr_dstaddr;
- if_data2->sin_addr.s_addr = 0;
- if_data2->sin_family = AF_INET;
- err = devinet_ioctl(SIOCSIFDSTADDR, &if_info);
- } else {
- if_data1 = (struct sockaddr_in *)&if_info.ifr_addr;
- if_data1->sin_addr.s_addr = 0;
- if_data1->sin_family = AF_INET;
- err = devinet_ioctl(SIOCSIFADDR,&if_info);
-
- }
- #else
- /* set the point-to-point IP address to 0.0.0.0 */
- dev->pa_dstaddr = 0;
- err = ip_rt_kill(&route);
- #endif
- if(err) {
- printk(KERN_INFO
- "%s: Remove route %u.%u.%u.%u failed, (err %d)n",
- card->devname, NIPQUAD(remote_IP_addr),
- err);
- } else {
- ((chdlc_private_area_t *)dev->priv)->route_status =
- NO_ROUTE;
- printk(KERN_INFO "%s: Dynamic route removed: %u.%u.%u.%un",
- card->devname, NIPQUAD(local_IP_addr));
- chdlc_priv_area->route_removed = 1;
- }
- break;
- }
- set_fs(fs); /* Restore file system */
- }
- /*=============================================================================
- * Store a UDP management packet for later processing.
- */
- static int store_udp_mgmt_pkt(char udp_pkt_src, sdla_t* card,
- struct sk_buff *skb, netdevice_t* dev,
- chdlc_private_area_t* chdlc_priv_area )
- {
- int udp_pkt_stored = 0;
- if(!chdlc_priv_area->udp_pkt_lgth &&
- (skb->len <= MAX_LGTH_UDP_MGNT_PKT)) {
- chdlc_priv_area->udp_pkt_lgth = skb->len;
- chdlc_priv_area->udp_pkt_src = udp_pkt_src;
- memcpy(chdlc_priv_area->udp_pkt_data, skb->data, skb->len);
- chdlc_priv_area->timer_int_enabled = TMR_INT_ENABLED_UDP;
- udp_pkt_stored = 1;
- }
- if(udp_pkt_src == UDP_PKT_FRM_STACK){
- wan_dev_kfree_skb(skb, FREE_WRITE);
- }else{
- wan_dev_kfree_skb(skb, FREE_READ);
- }
-
- return(udp_pkt_stored);
- }
- /*=============================================================================
- * Process UDP management packet.
- */
- static int process_udp_mgmt_pkt(sdla_t* card, netdevice_t* dev,
- chdlc_private_area_t* chdlc_priv_area )
- {
- unsigned char *buf;
- unsigned int frames, len;
- struct sk_buff *new_skb;
- unsigned short buffer_length, real_len;
- unsigned long data_ptr;
- unsigned data_length;
- int udp_mgmt_req_valid = 1;
- CHDLC_MAILBOX_STRUCT *mb = card->mbox;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- chdlc_udp_pkt_t *chdlc_udp_pkt;
- struct timeval tv;
- int err;
- char ut_char;
- chdlc_udp_pkt = (chdlc_udp_pkt_t *) chdlc_priv_area->udp_pkt_data;
- if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK){
- /* Only these commands are support for remote debugging.
- * All others are not */
- switch(chdlc_udp_pkt->cblock.command) {
- case READ_GLOBAL_STATISTICS:
- case READ_MODEM_STATUS:
- case READ_CHDLC_LINK_STATUS:
- case CPIPE_ROUTER_UP_TIME:
- case READ_COMMS_ERROR_STATS:
- case READ_CHDLC_OPERATIONAL_STATS:
- /* These two commands are executed for
- * each request */
- case READ_CHDLC_CONFIGURATION:
- case READ_CHDLC_CODE_VERSION:
- udp_mgmt_req_valid = 1;
- break;
- default:
- udp_mgmt_req_valid = 0;
- break;
- }
- }
-
- if(!udp_mgmt_req_valid) {
- /* set length to 0 */
- chdlc_udp_pkt->cblock.buffer_length = 0;
- /* set return code */
- chdlc_udp_pkt->cblock.return_code = 0xCD;
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Warning, Illegal UDP command attempted from network: %xn",
- card->devname,chdlc_udp_pkt->cblock.command);
- }
- } else {
- unsigned long trace_status_cfg_addr = 0;
- TRACE_STATUS_EL_CFG_STRUCT trace_cfg_struct;
- TRACE_STATUS_ELEMENT_STRUCT trace_element_struct;
- switch(chdlc_udp_pkt->cblock.command) {
- case CPIPE_ENABLE_TRACING:
- if (!chdlc_priv_area->TracingEnabled) {
- /* OPERATE_DATALINE_MONITOR */
- mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
- mb->command = SET_TRACE_CONFIGURATION;
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_config = TRACE_ACTIVE;
- /* Trace delay mode is not used because it slows
- down transfer and results in a standoff situation
- when there is a lot of data */
- /* Configure the Trace based on user inputs */
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->trace_config |=
- chdlc_udp_pkt->data[0];
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_deactivation_timer = 4000;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- card->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = err;
- mb->buffer_length = 0;
- break;
- }
- /* Get the base address of the trace element list */
- mb->buffer_length = 0;
- mb->command = READ_TRACE_CONFIGURATION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK) {
- chdlc_error(card,err,mb);
- chdlc_priv_area->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = err;
- mb->buffer_length = 0;
- break;
- }
- trace_status_cfg_addr =((LINE_TRACE_CONFIG_STRUCT *)
- mb->data) -> ptr_trace_stat_el_cfg_struct;
- sdla_peek(&card->hw, trace_status_cfg_addr,
- &trace_cfg_struct, sizeof(trace_cfg_struct));
-
- chdlc_priv_area->start_trace_addr = trace_cfg_struct.
- base_addr_trace_status_elements;
- chdlc_priv_area->number_trace_elements =
- trace_cfg_struct.number_trace_status_elements;
- chdlc_priv_area->end_trace_addr = (unsigned long)
- ((TRACE_STATUS_ELEMENT_STRUCT *)
- chdlc_priv_area->start_trace_addr +
- (chdlc_priv_area->number_trace_elements - 1));
- chdlc_priv_area->base_addr_trace_buffer =
- trace_cfg_struct.base_addr_trace_buffer;
- chdlc_priv_area->end_addr_trace_buffer =
- trace_cfg_struct.end_addr_trace_buffer;
- chdlc_priv_area->curr_trace_addr =
- trace_cfg_struct.next_trace_element_to_use;
- chdlc_priv_area->available_buffer_space = 2000 -
- sizeof(ip_pkt_t) -
- sizeof(udp_pkt_t) -
- sizeof(wp_mgmt_t) -
- sizeof(cblock_t) -
- sizeof(trace_info_t);
- }
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- mb->buffer_length = 0;
- chdlc_priv_area->TracingEnabled = 1;
- break;
-
- case CPIPE_DISABLE_TRACING:
- if (chdlc_priv_area->TracingEnabled) {
- /* OPERATE_DATALINE_MONITOR */
- mb->buffer_length = sizeof(LINE_TRACE_CONFIG_STRUCT);
- mb->command = SET_TRACE_CONFIGURATION;
- ((LINE_TRACE_CONFIG_STRUCT *)mb->data)->
- trace_config = TRACE_INACTIVE;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- }
- chdlc_priv_area->TracingEnabled = 0;
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- mb->buffer_length = 0;
- break;
-
- case CPIPE_GET_TRACE_INFO:
- if (!chdlc_priv_area->TracingEnabled) {
- chdlc_udp_pkt->cblock.return_code = 1;
- mb->buffer_length = 0;
- break;
- }
- chdlc_udp_pkt->trace_info.ismoredata = 0x00;
- buffer_length = 0; /* offset of packet already occupied */
- for (frames=0; frames < chdlc_priv_area->number_trace_elements; frames++){
- trace_pkt_t *trace_pkt = (trace_pkt_t *)
- &chdlc_udp_pkt->data[buffer_length];
- sdla_peek(&card->hw, chdlc_priv_area->curr_trace_addr,
- (unsigned char *)&trace_element_struct,
- sizeof(TRACE_STATUS_ELEMENT_STRUCT));
- if (trace_element_struct.opp_flag == 0x00) {
- break;
- }
- /* get pointer to real data */
- data_ptr = trace_element_struct.ptr_data_bfr;
- /* See if there is actual data on the trace buffer */
- if (data_ptr){
- data_length = trace_element_struct.trace_length;
- }else{
- data_length = 0;
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- }
-
- if( (chdlc_priv_area->available_buffer_space - buffer_length)
- < ( sizeof(trace_pkt_t) + data_length) ) {
- /* indicate there are more frames on board & exit */
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- break;
- }
- trace_pkt->status = trace_element_struct.trace_type;
- trace_pkt->time_stamp =
- trace_element_struct.trace_time_stamp;
- trace_pkt->real_length =
- trace_element_struct.trace_length;
- /* see if we can fit the frame into the user buffer */
- real_len = trace_pkt->real_length;
- if (data_ptr == 0) {
- trace_pkt->data_avail = 0x00;
- } else {
- unsigned tmp = 0;
- /* get the data from circular buffer
- must check for end of buffer */
- trace_pkt->data_avail = 0x01;
- if ((data_ptr + real_len) >
- chdlc_priv_area->end_addr_trace_buffer + 1){
- tmp = chdlc_priv_area->end_addr_trace_buffer - data_ptr + 1;
- sdla_peek(&card->hw, data_ptr,
- trace_pkt->data,tmp);
- data_ptr = chdlc_priv_area->base_addr_trace_buffer;
- }
-
- sdla_peek(&card->hw, data_ptr,
- &trace_pkt->data[tmp], real_len - tmp);
- }
- /* zero the opp flag to show we got the frame */
- ut_char = 0x00;
- sdla_poke(&card->hw, chdlc_priv_area->curr_trace_addr, &ut_char, 1);
- /* now move onto the next frame */
- chdlc_priv_area->curr_trace_addr += sizeof(TRACE_STATUS_ELEMENT_STRUCT);
- /* check if we went over the last address */
- if ( chdlc_priv_area->curr_trace_addr > chdlc_priv_area->end_trace_addr ) {
- chdlc_priv_area->curr_trace_addr = chdlc_priv_area->start_trace_addr;
- }
- if(trace_pkt->data_avail == 0x01) {
- buffer_length += real_len - 1;
- }
-
- /* for the header */
- buffer_length += sizeof(trace_pkt_t);
- } /* For Loop */
- if (frames == chdlc_priv_area->number_trace_elements){
- chdlc_udp_pkt->trace_info.ismoredata = 0x01;
- }
- chdlc_udp_pkt->trace_info.num_frames = frames;
-
- mb->buffer_length = buffer_length;
- chdlc_udp_pkt->cblock.buffer_length = buffer_length;
-
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
-
- break;
- case CPIPE_FT1_READ_STATUS:
- ((unsigned char *)chdlc_udp_pkt->data )[0] =
- flags->FT1_info_struct.parallel_port_A_input;
- ((unsigned char *)chdlc_udp_pkt->data )[1] =
- flags->FT1_info_struct.parallel_port_B_input;
-
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- chdlc_udp_pkt->cblock.buffer_length = 2;
- mb->buffer_length = 2;
- break;
- case CPIPE_ROUTER_UP_TIME:
- do_gettimeofday( &tv );
- chdlc_priv_area->router_up_time = tv.tv_sec -
- chdlc_priv_area->router_start_time;
- *(unsigned long *)&chdlc_udp_pkt->data =
- chdlc_priv_area->router_up_time;
- mb->buffer_length = sizeof(unsigned long);
- chdlc_udp_pkt->cblock.buffer_length = sizeof(unsigned long);
- chdlc_udp_pkt->cblock.return_code = COMMAND_OK;
- break;
- case FT1_MONITOR_STATUS_CTRL:
- /* Enable FT1 MONITOR STATUS */
- if ((chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_STATUS) ||
- (chdlc_udp_pkt->data[0] & ENABLE_READ_FT1_OP_STATS)) {
-
- if( rCount++ != 0 ) {
- chdlc_udp_pkt->cblock.
- return_code = COMMAND_OK;
- mb->buffer_length = 1;
- break;
- }
- }
- /* Disable FT1 MONITOR STATUS */
- if( chdlc_udp_pkt->data[0] == 0) {
- if( --rCount != 0) {
- chdlc_udp_pkt->cblock.
- return_code = COMMAND_OK;
- mb->buffer_length = 1;
- break;
- }
- }
- goto dflt_1;
- default:
- dflt_1:
- /* it's a board command */
- mb->command = chdlc_udp_pkt->cblock.command;
- mb->buffer_length = chdlc_udp_pkt->cblock.buffer_length;
- if (mb->buffer_length) {
- memcpy(&mb->data, (unsigned char *) chdlc_udp_pkt->
- data, mb->buffer_length);
- }
- /* run the command on the board */
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK) {
- break;
- }
- /* copy the result back to our buffer */
- memcpy(&chdlc_udp_pkt->cblock, mb, sizeof(cblock_t));
-
- if (mb->buffer_length) {
- memcpy(&chdlc_udp_pkt->data, &mb->data,
- mb->buffer_length);
- }
- } /* end of switch */
- } /* end of else */
- /* Fill UDP TTL */
- chdlc_udp_pkt->ip_pkt.ttl = card->wandev.ttl;
- len = reply_udp(chdlc_priv_area->udp_pkt_data, mb->buffer_length);
-
- if(chdlc_priv_area->udp_pkt_src == UDP_PKT_FRM_NETWORK){
- /* Must check if we interrupted if_send() routine. The
- * tx buffers might be used. If so drop the packet */
- if (!test_bit(SEND_CRIT,&card->wandev.critical)) {
-
- if(!chdlc_send(card, chdlc_priv_area->udp_pkt_data, len)) {
- ++ card->wandev.stats.tx_packets;
- #if defined(LINUX_2_1) || defined(LINUX_2_4)
- card->wandev.stats.tx_bytes += len;
- #endif
- }
- }
- } else {
-
- /* Pass it up the stack
- Allocate socket buffer */
- if ((new_skb = dev_alloc_skb(len)) != NULL) {
- /* copy data into new_skb */
- buf = skb_put(new_skb, len);
- memcpy(buf, chdlc_priv_area->udp_pkt_data, len);
- /* Decapsulate pkt and pass it up the protocol stack */
- new_skb->protocol = htons(ETH_P_IP);
- new_skb->dev = dev;
- new_skb->mac.raw = new_skb->data;
-
- netif_rx(new_skb);
- } else {
-
- printk(KERN_INFO "%s: no socket buffers available!n",
- card->devname);
- }
- }
-
- chdlc_priv_area->udp_pkt_lgth = 0;
-
- return 0;
- }
- /*============================================================================
- * Initialize Receive and Transmit Buffers.
- */
- static void init_chdlc_tx_rx_buff( sdla_t* card)
- {
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- CHDLC_TX_STATUS_EL_CFG_STRUCT *tx_config;
- CHDLC_RX_STATUS_EL_CFG_STRUCT *rx_config;
- char err;
-
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CONFIGURATION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if(err != COMMAND_OK) {
- if (card->wandev.dev){
- chdlc_error(card,err,mb);
- }
- return;
- }
- if(card->hw.type == SDLA_S514) {
- tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Tx_stat_el_cfg_struct));
- rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Rx_stat_el_cfg_struct));
- /* Setup Head and Tails for buffers */
- card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
- tx_config->base_addr_Tx_status_elements);
- card->u.c.txbuf_last =
- (CHDLC_DATA_TX_STATUS_EL_STRUCT *)
- card->u.c.txbuf_base +
- (tx_config->number_Tx_status_elements - 1);
- card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
- rx_config->base_addr_Rx_status_elements);
- card->u.c.rxbuf_last =
- (CHDLC_DATA_RX_STATUS_EL_STRUCT *)
- card->u.c.rxbuf_base +
- (rx_config->number_Rx_status_elements - 1);
- /* Set up next pointer to be used */
- card->u.c.txbuf = (void *)(card->hw.dpmbase +
- tx_config->next_Tx_status_element_to_use);
- card->u.c.rxmb = (void *)(card->hw.dpmbase +
- rx_config->next_Rx_status_element_to_use);
- }
- else {
- tx_config = (CHDLC_TX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Tx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
- rx_config = (CHDLC_RX_STATUS_EL_CFG_STRUCT *)(card->hw.dpmbase +
- (((CHDLC_CONFIGURATION_STRUCT *)mb->data)->
- ptr_CHDLC_Rx_stat_el_cfg_struct % SDLA_WINDOWSIZE));
- /* Setup Head and Tails for buffers */
- card->u.c.txbuf_base = (void *)(card->hw.dpmbase +
- (tx_config->base_addr_Tx_status_elements % SDLA_WINDOWSIZE));
- card->u.c.txbuf_last =
- (CHDLC_DATA_TX_STATUS_EL_STRUCT *)card->u.c.txbuf_base
- + (tx_config->number_Tx_status_elements - 1);
- card->u.c.rxbuf_base = (void *)(card->hw.dpmbase +
- (rx_config->base_addr_Rx_status_elements % SDLA_WINDOWSIZE));
- card->u.c.rxbuf_last =
- (CHDLC_DATA_RX_STATUS_EL_STRUCT *)card->u.c.rxbuf_base
- + (rx_config->number_Rx_status_elements - 1);
- /* Set up next pointer to be used */
- card->u.c.txbuf = (void *)(card->hw.dpmbase +
- (tx_config->next_Tx_status_element_to_use % SDLA_WINDOWSIZE));
- card->u.c.rxmb = (void *)(card->hw.dpmbase +
- (rx_config->next_Rx_status_element_to_use % SDLA_WINDOWSIZE));
- }
- /* Setup Actual Buffer Start and end addresses */
- card->u.c.rx_base = rx_config->base_addr_Rx_buffer;
- card->u.c.rx_top = rx_config->end_addr_Rx_buffer;
- }
- /*=============================================================================
- * Perform Interrupt Test by running READ_CHDLC_CODE_VERSION command MAX_INTR
- * _TEST_COUNTER times.
- */
- static int intr_test( sdla_t* card)
- {
- CHDLC_MAILBOX_STRUCT* mb = card->mbox;
- int err,i;
- Intr_test_counter = 0;
-
- err = chdlc_set_intr_mode(card, APP_INT_ON_COMMAND_COMPLETE);
- if (err == CMD_OK) {
- for (i = 0; i < MAX_INTR_TEST_COUNTER; i ++) {
- mb->buffer_length = 0;
- mb->command = READ_CHDLC_CODE_VERSION;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != CMD_OK)
- chdlc_error(card, err, mb);
- }
- }
- else {
- return err;
- }
- err = chdlc_set_intr_mode(card, 0);
- if (err != CMD_OK)
- return err;
- return 0;
- }
- /*==============================================================================
- * Determine what type of UDP call it is. CPIPEAB ?
- */
- static int udp_pkt_type(struct sk_buff *skb, sdla_t* card)
- {
- chdlc_udp_pkt_t *chdlc_udp_pkt = (chdlc_udp_pkt_t *)skb->data;
- #ifdef _WAN_UDP_DEBUG
- printk(KERN_INFO "SIG %s = %sn
- UPP %x = %xn
- PRT %x = %xn
- REQ %i = %in
- 36 th = %x 37th = %xn",
- chdlc_udp_pkt->wp_mgmt.signature,
- UDPMGMT_SIGNATURE,
- chdlc_udp_pkt->udp_pkt.udp_dst_port,
- ntohs(card->wandev.udp_port),
- chdlc_udp_pkt->ip_pkt.protocol,
- UDPMGMT_UDP_PROTOCOL,
- chdlc_udp_pkt->wp_mgmt.request_reply,
- UDPMGMT_REQUEST,
- skb->data[36], skb->data[37]);
- #endif
-
- if (!strncmp(chdlc_udp_pkt->wp_mgmt.signature,UDPMGMT_SIGNATURE,8) &&
- (chdlc_udp_pkt->udp_pkt.udp_dst_port == ntohs(card->wandev.udp_port)) &&
- (chdlc_udp_pkt->ip_pkt.protocol == UDPMGMT_UDP_PROTOCOL) &&
- (chdlc_udp_pkt->wp_mgmt.request_reply == UDPMGMT_REQUEST)) {
- return UDP_CPIPE_TYPE;
- }else{
- return UDP_INVALID_TYPE;
- }
- }
- /*============================================================================
- * Set PORT state.
- */
- static void port_set_state (sdla_t *card, int state)
- {
- if (card->u.c.state != state)
- {
- switch (state)
- {
- case WAN_CONNECTED:
- printk (KERN_INFO "%s: Link connected!n",
- card->devname);
- break;
- case WAN_CONNECTING:
- printk (KERN_INFO "%s: Link connecting...n",
- card->devname);
- break;
- case WAN_DISCONNECTED:
- printk (KERN_INFO "%s: Link disconnected!n",
- card->devname);
- break;
- }
- card->wandev.state = card->u.c.state = state;
- if (card->wandev.dev){
- netdevice_t *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- chdlc_priv_area->common.state = state;
- }
- }
- }
- /*===========================================================================
- * config_chdlc
- *
- * Configure the chdlc protocol and enable communications.
- *
- * The if_open() function binds this function to the poll routine.
- * Therefore, this function will run every time the chdlc interface
- * is brought up. We cannot run this function from the if_open
- * because if_open does not have access to the remote IP address.
- *
- * If the communications are not enabled, proceed to configure
- * the card and enable communications.
- *
- * If the communications are enabled, it means that the interface
- * was shutdown by ether the user or driver. In this case, we
- * have to check that the IP addresses have not changed. If
- * the IP addresses have changed, we have to reconfigure the firmware
- * and update the changed IP addresses. Otherwise, just exit.
- *
- */
- static int config_chdlc (sdla_t *card)
- {
- netdevice_t *dev = card->wandev.dev;
- chdlc_private_area_t *chdlc_priv_area = dev->priv;
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- if (card->u.c.comm_enabled){
- /* Jun 20. 2000: NC
- * IP addresses are not used in the API mode */
-
- if ((chdlc_priv_area->ip_local_tmp != chdlc_priv_area->ip_local ||
- chdlc_priv_area->ip_remote_tmp != chdlc_priv_area->ip_remote) &&
- card->u.c.usedby == WANPIPE) {
-
- /* The IP addersses have changed, we must
- * stop the communications and reconfigure
- * the card. Reason: the firmware must know
- * the local and remote IP addresses. */
- disable_comm(card);
- port_set_state(card, WAN_DISCONNECTED);
- printk(KERN_INFO
- "%s: IP addresses changed!n",
- card->devname);
- printk(KERN_INFO
- "%s: Restarting communications ...n",
- card->devname);
- }else{
- /* IP addresses are the same and the link is up,
- * we dont have to do anything here. Therefore, exit */
- return 0;
- }
- }
- chdlc_priv_area->ip_local = chdlc_priv_area->ip_local_tmp;
- chdlc_priv_area->ip_remote = chdlc_priv_area->ip_remote_tmp;
- /* Setup the Board for asynchronous mode */
- if (card->u.c.async_mode){
-
- if (set_asy_config(card)) {
- printk (KERN_INFO "%s: Failed CHDLC Async configuration!n",
- card->devname);
- return 0;
- }
- }else{
- /* Setup the Board for CHDLC */
- if (set_chdlc_config(card)) {
- printk (KERN_INFO "%s: Failed CHDLC configuration!n",
- card->devname);
- return 0;
- }
- }
- /* Set interrupt mode and mask */
- if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME |
- APP_INT_ON_GLOBAL_EXCEP_COND |
- APP_INT_ON_TX_FRAME |
- APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){
- printk (KERN_INFO "%s: Failed to set interrupt triggers!n",
- card->devname);
- return 0;
- }
-
- /* Mask the Transmit and Timer interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER);
- /* In TTY mode, receive interrupt will be enabled during
- * wanpipe_tty_open() operation */
- if (card->tty_opt){
- flags->interrupt_info_struct.interrupt_permission &= ~APP_INT_ON_RX_FRAME;
- }
- /* Enable communications */
- if (card->u.c.async_mode){
- if (asy_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable async commnunication!n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return 0;
- }
- }else{
- if (chdlc_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable chdlc communications!n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return 0;
- }
- }
- /* Initialize Rx/Tx buffer control fields */
- init_chdlc_tx_rx_buff(card);
- port_set_state(card, WAN_CONNECTING);
- return 0;
- }
- /*============================================================
- * chdlc_poll
- *
- * Rationale:
- * We cannot manipulate the routing tables, or
- * ip addresses withing the interrupt. Therefore
- * we must perform such actons outside an interrupt
- * at a later time.
- *
- * Description:
- * CHDLC polling routine, responsible for
- * shutting down interfaces upon disconnect
- * and adding/removing routes.
- *
- * Usage:
- * This function is executed for each CHDLC
- * interface through a tq_schedule bottom half.
- *
- * trigger_chdlc_poll() function is used to kick
- * the chldc_poll routine.
- */
- static void chdlc_poll (netdevice_t *dev)
- {
- chdlc_private_area_t *chdlc_priv_area;
- sdla_t *card;
- u8 check_gateway=0;
- SHARED_MEMORY_INFO_STRUCT* flags;
-
- if (!dev || (chdlc_priv_area=dev->priv) == NULL)
- return;
- card = chdlc_priv_area->card;
- flags = card->u.c.flags;
-
- /* (Re)Configuraiton is in progress, stop what you are
- * doing and get out */
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- clear_bit(POLL_CRIT,&card->wandev.critical);
- return;
- }
-
- /* if_open() function has triggered the polling routine
- * to determine the configured IP addresses. Once the
- * addresses are found, trigger the chdlc configuration */
- if (test_bit(0,&chdlc_priv_area->config_chdlc)){
- chdlc_priv_area->ip_local_tmp = get_ip_address(dev,WAN_LOCAL_IP);
- chdlc_priv_area->ip_remote_tmp = get_ip_address(dev,WAN_POINTOPOINT_IP);
-
- /* Jun 20. 2000 Bug Fix
- * Only perform this check in WANPIPE mode, since
- * IP addresses are not used in the API mode. */
-
- if (chdlc_priv_area->ip_local_tmp == chdlc_priv_area->ip_remote_tmp &&
- card->u.c.slarp_timer == 0x00 &&
- !card->u.c.backup &&
- card->u.c.usedby == WANPIPE){
- if (++chdlc_priv_area->ip_error > MAX_IP_ERRORS){
- printk(KERN_INFO "n%s: --- WARNING ---n",
- card->devname);
- printk(KERN_INFO
- "%s: The local IP address is the same as then",
- card->devname);
- printk(KERN_INFO
- "%s: Point-to-Point IP address.n",
- card->devname);
- printk(KERN_INFO "%s: --- WARNING ---nn",
- card->devname);
- }else{
- clear_bit(POLL_CRIT,&card->wandev.critical);
- chdlc_priv_area->poll_delay_timer.expires = jiffies+HZ;
- add_timer(&chdlc_priv_area->poll_delay_timer);
- return;
- }
- }
- clear_bit(0,&chdlc_priv_area->config_chdlc);
- clear_bit(POLL_CRIT,&card->wandev.critical);
-
- chdlc_priv_area->timer_int_enabled |= TMR_INT_ENABLED_CONFIG;
- flags->interrupt_info_struct.interrupt_permission |= APP_INT_ON_TIMER;
- return;
- }
- /* Dynamic interface implementation, as well as dynamic
- * routing. */
-
- switch (card->u.c.state){
- case WAN_DISCONNECTED:
- /* If the dynamic interface configuration is on, and interface
- * is up, then bring down the netowrk interface */
-
- if (test_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down) &&
- !test_bit(DEV_DOWN, &chdlc_priv_area->interface_down) &&
- card->wandev.dev->flags & IFF_UP){
- printk(KERN_INFO "%s: Interface %s down.n",
- card->devname,card->wandev.dev->name);
- change_dev_flags(card->wandev.dev,(card->wandev.dev->flags&~IFF_UP));
- set_bit(DEV_DOWN,&chdlc_priv_area->interface_down);
- chdlc_priv_area->route_status = NO_ROUTE;
- }else{
- /* We need to check if the local IP address is
- * zero. If it is, we shouldn't try to remove it.
- */
- if (card->wandev.dev->flags & IFF_UP &&
- get_ip_address(card->wandev.dev,WAN_LOCAL_IP) &&
- chdlc_priv_area->route_status != NO_ROUTE &&
- card->u.c.slarp_timer){
- process_route(card);
- }
- }
- break;
- case WAN_CONNECTED:
- /* In SMP machine this code can execute before the interface
- * comes up. In this case, we must make sure that we do not
- * try to bring up the interface before dev_open() is finished */
- /* DEV_DOWN will be set only when we bring down the interface
- * for the very first time. This way we know that it was us
- * that brought the interface down */
-
- if (test_bit(DYN_OPT_ON,&chdlc_priv_area->interface_down) &&
- test_bit(DEV_DOWN, &chdlc_priv_area->interface_down) &&
- !(card->wandev.dev->flags & IFF_UP)){
-
- printk(KERN_INFO "%s: Interface %s up.n",
- card->devname,card->wandev.dev->name);
- change_dev_flags(card->wandev.dev,(card->wandev.dev->flags|IFF_UP));
- clear_bit(DEV_DOWN,&chdlc_priv_area->interface_down);
- check_gateway=1;
- }
- if (chdlc_priv_area->route_status == ADD_ROUTE &&
- card->u.c.slarp_timer){
- process_route(card);
- check_gateway=1;
- }
- if (chdlc_priv_area->gateway && check_gateway)
- add_gateway(card,dev);
- break;
- }
- clear_bit(POLL_CRIT,&card->wandev.critical);
- }
- /*============================================================
- * trigger_chdlc_poll
- *
- * Description:
- * Add a chdlc_poll() task into a tq_scheduler bh handler
- * for a specific dlci/interface. This will kick
- * the fr_poll() routine at a later time.
- *
- * Usage:
- * Interrupts use this to defer a taks to
- * a polling routine.
- *
- */
- static void trigger_chdlc_poll (netdevice_t *dev)
- {
- chdlc_private_area_t *chdlc_priv_area;
- sdla_t *card;
- if (!dev)
- return;
-
- if ((chdlc_priv_area = dev->priv)==NULL)
- return;
- card = chdlc_priv_area->card;
-
- if (test_and_set_bit(POLL_CRIT,&card->wandev.critical)){
- return;
- }
- if (test_bit(PERI_CRIT,&card->wandev.critical)){
- return;
- }
- #ifdef LINUX_2_4
- schedule_task(&chdlc_priv_area->poll_task);
- #else
- queue_task(&chdlc_priv_area->poll_task, &tq_scheduler);
- #endif
- return;
- }
- static void chdlc_poll_delay (unsigned long dev_ptr)
- {
- netdevice_t *dev = (netdevice_t *)dev_ptr;
- trigger_chdlc_poll(dev);
- }
- void s508_lock (sdla_t *card, unsigned long *smp_flags)
- {
- #if defined(__SMP__) || defined(LINUX_2_4)
- spin_lock_irqsave(&card->wandev.lock, *smp_flags);
- if (card->next){
- spin_lock(&card->next->wandev.lock);
- }
- #else
- disable_irq(card->hw.irq);
- #endif
- }
- void s508_unlock (sdla_t *card, unsigned long *smp_flags)
- {
- #if defined(__SMP__) || defined(LINUX_2_4)
- if (card->next){
- spin_unlock(&card->next->wandev.lock);
- }
- spin_unlock_irqrestore(&card->wandev.lock, *smp_flags);
- #else
- enable_irq(card->hw.irq);
- #endif
- }
- //*********** TTY SECTION ****************
- #if defined(LINUX_2_4) || defined(LINUX_2_1)
- static void wanpipe_tty_trigger_tx_irq(sdla_t *card)
- {
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- INTERRUPT_INFORMATION_STRUCT *chdlc_int = &flags->interrupt_info_struct;
- chdlc_int->interrupt_permission |= APP_INT_ON_TX_FRAME;
- }
- static void wanpipe_tty_trigger_poll(sdla_t *card)
- {
- #ifdef LINUX_2_4
- schedule_task(&card->tty_task_queue);
- #else
- queue_task(&card->tty_task_queue, &tq_scheduler);
- #endif
- }
- static void tty_poll_task (void* data)
- {
- sdla_t *card = (sdla_t*)data;
- struct tty_struct *tty;
- if ((tty=card->tty)==NULL)
- return;
-
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup){
- (tty->ldisc.write_wakeup)(tty);
- }
- wake_up_interruptible(&tty->write_wait);
- #if defined(SERIAL_HAVE_POLL_WAIT) ||
- (defined LINUX_2_1 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15))
- wake_up_interruptible(&tty->poll_wait);
- #endif
- return;
- }
- static void wanpipe_tty_close(struct tty_struct *tty, struct file * filp)
- {
- sdla_t *card;
- unsigned long smp_flags;
-
- if (!tty || !tty->driver_data){
- return;
- }
-
- card = (sdla_t*)tty->driver_data;
-
- if (!card)
- return;
- printk(KERN_INFO "%s: Closing TTY Driver!n",
- card->devname);
- /* Sanity Check */
- if (!card->tty_open)
- return;
-
- wanpipe_close(card);
- if (--card->tty_open == 0){
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- card->tty=NULL;
- chdlc_disable_comm_shutdown(card);
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- if (card->tty_buf){
- kfree(card->tty_buf);
- card->tty_buf=NULL;
- }
- if (card->tty_rx){
- kfree(card->tty_rx);
- card->tty_rx=NULL;
- }
- }
- return;
- }
- static int wanpipe_tty_open(struct tty_struct *tty, struct file * filp)
- {
- unsigned long smp_flags;
- sdla_t *card;
-
- if (!tty){
- return -ENODEV;
- }
-
- if (!tty->driver_data){
- int port;
- port = MINOR(tty->device) - tty->driver.minor_start;
- if ((port < 0) || (port >= NR_PORTS))
- return -ENODEV;
-
- tty->driver_data = WAN_CARD(port);
- if (!tty->driver_data)
- return -ENODEV;
- }
- card = (sdla_t*)tty->driver_data;
- if (!card){
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- card->tty=NULL;
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- return -ENODEV;
- }
- printk(KERN_INFO "%s: Opening TTY Driver!n",
- card->devname);
- if (card->tty_open == 0){
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- card->tty=tty;
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- if (!card->tty_buf){
- card->tty_buf = kmalloc(TTY_CHDLC_MAX_MTU, GFP_KERNEL);
- if (!card->tty_buf){
- card->tty_buf=NULL;
- card->tty=NULL;
- return -ENOMEM;
- }
- }
- if (!card->tty_rx){
- card->tty_rx = kmalloc(TTY_CHDLC_MAX_MTU, GFP_KERNEL);
- if (!card->tty_rx){
- /* Free the buffer above */
- kfree(card->tty_buf);
- card->tty_buf=NULL;
- card->tty=NULL;
- return -ENOMEM;
- }
- }
- }
- ++card->tty_open;
- wanpipe_open(card);
- return 0;
- }
- static int wanpipe_tty_write(struct tty_struct * tty, int from_user,
- const unsigned char *buf, int count)
- {
- unsigned long smp_flags=0;
- sdla_t *card=NULL;
- if (!tty){
- dbg_printk(KERN_INFO "NO TTY in Writen");
- return -ENODEV;
- }
- card = (sdla_t *)tty->driver_data;
-
- if (!card){
- dbg_printk(KERN_INFO "No Card in TTY Writen");
- return -ENODEV;
- }
- if (count > card->wandev.mtu){
- dbg_printk(KERN_INFO "Frame too big in Write %i Max: %in",
- count,card->wandev.mtu);
- return -EINVAL;
- }
-
- if (card->wandev.state != WAN_CONNECTED){
- dbg_printk(KERN_INFO "Card not connected in TTY Writen");
- return -EINVAL;
- }
- /* Lock the 508 Card: SMP is supported */
- if(card->hw.type != SDLA_S514){
- s508_lock(card,&smp_flags);
- }
-
- if (test_and_set_bit(SEND_CRIT,(void*)&card->wandev.critical)){
- printk(KERN_INFO "%s: Critical in TTY Writen",
- card->devname);
-
- /* Lock the 508 Card: SMP is supported */
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
-
- return -EINVAL;
- }
-
- if (from_user) {
-
- unsigned char *tmp_buf;
-
- if ((tmp_buf=card->tty_buf)==NULL){
- dbg_printk(KERN_INFO "No TTY BUF in Writen");
-
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
-
- return -ENOMEM;
- }
-
- if (copy_from_user(tmp_buf,buf,count)){
- dbg_printk(KERN_INFO "%s: Failed to copy from user!n",
- card->devname);
-
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
-
- return -EINVAL;
- }
- if (chdlc_send(card,(void*)tmp_buf,count)){
- dbg_printk(KERN_INFO "%s: Failed to send, retry later: user!n",
- card->devname);
-
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-
- wanpipe_tty_trigger_tx_irq(card);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
- return 0;
- }
- }else{
- if (chdlc_send(card,(void*)buf,count)){
- dbg_printk(KERN_INFO "%s: Failed to send, retry later: kernel!n",
- card->devname);
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-
- wanpipe_tty_trigger_tx_irq(card);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
- return 0;
- }
- }
- dbg_printk(KERN_INFO "%s: Packet sent OK: %in",card->devname,count);
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
- return count;
- }
- static void wanpipe_tty_receive(sdla_t *card, unsigned addr, unsigned int len)
- {
- unsigned offset=0;
- unsigned olen=len;
- char fp=0;
- struct tty_struct *tty;
- int i;
-
- if (!card->tty_open){
- dbg_printk(KERN_INFO "%s: TTY not open during receiven",
- card->devname);
- return;
- }
-
- if ((tty=card->tty) == NULL){
- dbg_printk(KERN_INFO "%s: No TTY on receiven",
- card->devname);
- return;
- }
-
- if (!tty->driver_data){
- dbg_printk(KERN_INFO "%s: No Driver Data, or Flip on receiven",
- card->devname);
- return;
- }
-
- if (card->u.c.async_mode){
- if ((tty->flip.count+len) >= TTY_FLIPBUF_SIZE){
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Received packet size too big: %i bytes, Max: %i!n",
- card->devname,len,TTY_FLIPBUF_SIZE);
- }
- return;
- }
-
- if((addr + len) > card->u.c.rx_top + 1) {
- offset = card->u.c.rx_top - addr + 1;
-
- sdla_peek(&card->hw, addr, tty->flip.char_buf_ptr, offset);
-
- addr = card->u.c.rx_base;
- len -= offset;
-
- tty->flip.char_buf_ptr+=offset;
- tty->flip.count+=offset;
- for (i=0;i<offset;i++){
- *tty->flip.flag_buf_ptr = 0;
- tty->flip.flag_buf_ptr++;
- }
- }
-
- sdla_peek(&card->hw, addr, tty->flip.char_buf_ptr, len);
-
- tty->flip.char_buf_ptr+=len;
- card->tty->flip.count+=len;
- for (i=0;i<len;i++){
- *tty->flip.flag_buf_ptr = 0;
- tty->flip.flag_buf_ptr++;
- }
- tty->low_latency=1;
- tty_flip_buffer_push(tty);
- }else{
- if (!card->tty_rx){
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Receive sync buffer not available!n",
- card->devname);
- }
- return;
- }
-
- if (len > TTY_CHDLC_MAX_MTU){
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: Received packet size too big: %i bytes, Max: %i!n",
- card->devname,len,TTY_FLIPBUF_SIZE);
- }
- return;
- }
-
- if((addr + len) > card->u.c.rx_top + 1) {
- offset = card->u.c.rx_top - addr + 1;
-
- sdla_peek(&card->hw, addr, card->tty_rx, offset);
-
- addr = card->u.c.rx_base;
- len -= offset;
- }
- sdla_peek(&card->hw, addr, card->tty_rx+offset, len);
- if (tty->ldisc.receive_buf){
- tty->ldisc.receive_buf(tty,card->tty_rx,&fp,olen);
- }else{
- if (net_ratelimit()){
- printk(KERN_INFO
- "%s: NO TTY Sync line discipline!n",
- card->devname);
- }
- }
- }
- dbg_printk(KERN_INFO "%s: Received Data %in",card->devname,olen);
- return;
- }
- #if 0
- static int wanpipe_tty_ioctl(struct tty_struct *tty, struct file * file,
- unsigned int cmd, unsigned long arg)
- {
- return -ENOIOCTLCMD;
- }
- #endif
- static void wanpipe_tty_stop(struct tty_struct *tty)
- {
- return;
- }
- static void wanpipe_tty_start(struct tty_struct *tty)
- {
- return;
- }
- static int config_tty (sdla_t *card)
- {
- SHARED_MEMORY_INFO_STRUCT *flags = card->u.c.flags;
- /* Setup the Board for asynchronous mode */
- if (card->u.c.async_mode){
-
- if (set_asy_config(card)) {
- printk (KERN_INFO "%s: Failed CHDLC Async configuration!n",
- card->devname);
- return -EINVAL;
- }
- }else{
- /* Setup the Board for CHDLC */
- if (set_chdlc_config(card)) {
- printk (KERN_INFO "%s: Failed CHDLC configuration!n",
- card->devname);
- return -EINVAL;
- }
- }
- /* Set interrupt mode and mask */
- if (chdlc_set_intr_mode(card, APP_INT_ON_RX_FRAME |
- APP_INT_ON_GLOBAL_EXCEP_COND |
- APP_INT_ON_TX_FRAME |
- APP_INT_ON_CHDLC_EXCEP_COND | APP_INT_ON_TIMER)){
- printk (KERN_INFO "%s: Failed to set interrupt triggers!n",
- card->devname);
- return -EINVAL;
- }
-
- /* Mask the Transmit and Timer interrupt */
- flags->interrupt_info_struct.interrupt_permission &=
- ~(APP_INT_ON_TX_FRAME | APP_INT_ON_TIMER);
-
- /* Enable communications */
- if (card->u.c.async_mode){
- if (asy_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable async commnunication!n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return -EINVAL;
- }
- }else{
- if (chdlc_comm_enable(card) != 0) {
- printk(KERN_INFO "%s: Failed to enable chdlc communications!n",
- card->devname);
- flags->interrupt_info_struct.interrupt_permission = 0;
- card->u.c.comm_enabled=0;
- chdlc_set_intr_mode(card,0);
- return -EINVAL;
- }
- }
- /* Initialize Rx/Tx buffer control fields */
- init_chdlc_tx_rx_buff(card);
- port_set_state(card, WAN_CONNECTING);
- return 0;
- }
- static int change_speed(sdla_t *card, struct tty_struct *tty,
- struct termios *old_termios)
- {
- int baud, ret=0;
- unsigned cflag;
- int dbits,sbits,parity,handshaking;
- cflag = tty->termios->c_cflag;
- /* There is always one stop bit */
- sbits=WANOPT_ONE;
-
- /* Parity is defaulted to NONE */
- parity = WANOPT_NONE;
- handshaking=0;
-
- /* byte size and parity */
- switch (cflag & CSIZE) {
- case CS5: dbits = 5; break;
- case CS6: dbits = 6; break;
- case CS7: dbits = 7; break;
- case CS8: dbits = 8; break;
- /* Never happens, but GCC is too dumb to figure it out */
- default: dbits = 8; break;
- }
-
- /* One more stop bit should be supported, thus increment
- * the number of stop bits Max=2 */
- if (cflag & CSTOPB) {
- sbits = WANOPT_TWO;
- }
- if (cflag & PARENB) {
- parity = WANOPT_EVEN;
- }
- if (cflag & PARODD){
- parity = WANOPT_ODD;
- }
- /* Determine divisor based on baud rate */
- baud = tty_get_baud_rate(tty);
- if (!baud)
- baud = 9600; /* B0 transition handled in rs_set_termios */
- if (cflag & CRTSCTS) {
- handshaking|=ASY_RTS_HS_FOR_RX;
- }
-
- if (I_IGNPAR(tty))
- parity = WANOPT_NONE;
- if (I_IXOFF(tty)){
- handshaking|=ASY_XON_XOFF_HS_FOR_RX;
- handshaking|=ASY_XON_XOFF_HS_FOR_TX;
- }
- if (I_IXON(tty)){
- handshaking|=ASY_XON_XOFF_HS_FOR_RX;
- handshaking|=ASY_XON_XOFF_HS_FOR_TX;
- }
- if (card->u.c.async_mode){
- if (card->wandev.bps != baud)
- ret=1;
- card->wandev.bps = baud;
- }
- if (card->u.c.async_mode){
- if (card->u.c.protocol_options != handshaking)
- ret=1;
- card->u.c.protocol_options = handshaking;
- if (card->u.c.tx_bits_per_char != dbits)
- ret=1;
- card->u.c.tx_bits_per_char = dbits;
- if (card->u.c.rx_bits_per_char != dbits)
- ret=1;
- card->u.c.rx_bits_per_char = dbits;
-
- if (card->u.c.stop_bits != sbits)
- ret=1;
- card->u.c.stop_bits = sbits;
- if (card->u.c.parity != parity)
- ret=1;
- card->u.c.parity = parity;
- card->u.c.break_timer = 50;
- card->u.c.inter_char_timer = 10;
- card->u.c.rx_complete_length = 100;
- card->u.c.xon_char = 0xFE;
- }else{
- card->u.c.protocol_options = HDLC_STREAMING_MODE;
- }
-
- return ret;
- }
-
- static void wanpipe_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
- {
- sdla_t *card;
- int err=1;
- if (!tty){
- return;
- }
- card = (sdla_t *)tty->driver_data;
-
- if (!card)
- return;
- if (change_speed(card, tty, old_termios) || !card->u.c.comm_enabled){
- unsigned long smp_flags;
-
- if (card->u.c.comm_enabled){
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- chdlc_disable_comm_shutdown(card);
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- }
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- err = config_tty(card);
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- if (card->u.c.async_mode){
- printk(KERN_INFO "%s: TTY Async Configuration:n"
- " Baud =%in"
- " Handshaking =%sn"
- " Tx Dbits =%in"
- " Rx Dbits =%in"
- " Parity =%sn"
- " Stop Bits =%in",
- card->devname,
- card->wandev.bps,
- opt_decode[card->u.c.protocol_options],
- card->u.c.tx_bits_per_char,
- card->u.c.rx_bits_per_char,
- p_decode[card->u.c.parity] ,
- card->u.c.stop_bits);
- }else{
- printk(KERN_INFO "%s: TTY Sync Configuration:n"
- " Baud =%in"
- " Protocol =HDLC_STREAMINGn",
- card->devname,card->wandev.bps);
- }
- if (!err){
- port_set_state(card,WAN_CONNECTED);
- }else{
- port_set_state(card,WAN_DISCONNECTED);
- }
- }
- return;
- }
- static void wanpipe_tty_put_char(struct tty_struct *tty, unsigned char ch)
- {
- sdla_t *card;
- unsigned long smp_flags=0;
- if (!tty){
- return;
- }
-
- card = (sdla_t *)tty->driver_data;
-
- if (!card)
- return;
- if (card->wandev.state != WAN_CONNECTED)
- return;
- if(card->hw.type != SDLA_S514)
- s508_lock(card,&smp_flags);
-
- if (test_and_set_bit(SEND_CRIT,(void*)&card->wandev.critical)){
-
- wanpipe_tty_trigger_tx_irq(card);
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
- return;
- }
- if (chdlc_send(card,(void*)&ch,1)){
- wanpipe_tty_trigger_tx_irq(card);
- dbg_printk("%s: Failed to TX char!n",card->devname);
- }
-
- dbg_printk("%s: Char TX OKn",card->devname);
-
- clear_bit(SEND_CRIT,(void*)&card->wandev.critical);
-
- if(card->hw.type != SDLA_S514)
- s508_unlock(card,&smp_flags);
-
- return;
- }
- static void wanpipe_tty_flush_chars(struct tty_struct *tty)
- {
- return;
- }
- static void wanpipe_tty_flush_buffer(struct tty_struct *tty)
- {
- if (!tty)
- return;
-
- wake_up_interruptible(&tty->write_wait);
- #if defined(SERIAL_HAVE_POLL_WAIT) ||
- (defined LINUX_2_1 && LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,15))
- wake_up_interruptible(&tty->poll_wait);
- #endif
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup)(tty);
- return;
- }
- /*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
- static void wanpipe_tty_send_xchar(struct tty_struct *tty, char ch)
- {
- return;
- }
- static int wanpipe_tty_chars_in_buffer(struct tty_struct *tty)
- {
- return 0;
- }
- static int wanpipe_tty_write_room(struct tty_struct *tty)
- {
- sdla_t *card;
- printk(KERN_INFO "TTY Write Roomn");
-
- if (!tty){
- return 0;
- }
- card = (sdla_t *)tty->driver_data;
- if (!card)
- return 0;
- if (card->wandev.state != WAN_CONNECTED)
- return 0;
-
- return SEC_MAX_NO_DATA_BYTES_IN_FRAME;
- }
- static int set_modem_status(sdla_t *card, unsigned char data)
- {
- CHDLC_MAILBOX_STRUCT *mb = card->mbox;
- int err;
- mb->buffer_length=1;
- mb->command=SET_MODEM_STATUS;
- mb->data[0]=data;
- err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
- if (err != COMMAND_OK)
- chdlc_error (card, err, mb);
-
- return err;
- }
- static void wanpipe_tty_hangup(struct tty_struct *tty)
- {
- sdla_t *card;
- unsigned long smp_flags;
- printk(KERN_INFO "TTY Hangup!n");
-
- if (!tty){
- return;
- }
- card = (sdla_t *)tty->driver_data;
- if (!card)
- return;
- lock_adapter_irq(&card->wandev.lock,&smp_flags);
- set_modem_status(card,0);
- unlock_adapter_irq(&card->wandev.lock,&smp_flags);
- return;
- }
- static void wanpipe_tty_break(struct tty_struct *tty, int break_state)
- {
- return;
- }
- static void wanpipe_tty_wait_until_sent(struct tty_struct *tty, int timeout)
- {
- return;
- }
- static void wanpipe_tty_throttle(struct tty_struct * tty)
- {
- return;
- }
- static void wanpipe_tty_unthrottle(struct tty_struct * tty)
- {
- return;
- }
- int wanpipe_tty_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
- {
- return 0;
- }
- /*
- * The serial driver boot-time initialization code!
- */
- int wanpipe_tty_init(sdla_t *card)
- {
- struct serial_state * state;
-
- /* Initialize the tty_driver structure */
- if (card->tty_minor < 0 || card->tty_minor > NR_PORTS){
- printk(KERN_INFO "%s: Illegal Minor TTY number (0-4): %in",
- card->devname,card->tty_minor);
- return -EINVAL;
- }
- if (WAN_CARD(card->tty_minor)){
- printk(KERN_INFO "%s: TTY Minor %i, already in usen",
- card->devname,card->tty_minor);
- return -EBUSY;
- }
- if (tty_init_cnt==0){
-
- printk(KERN_INFO "%s: TTY %s Driver Init: Major %i, Minor Range %i-%in",
- card->devname,
- card->u.c.async_mode ? "ASYNC" : "SYNC",
- WAN_TTY_MAJOR,MIN_PORT,MAX_PORT);
-
- tty_driver_mode = card->u.c.async_mode;
-
- memset(&serial_driver, 0, sizeof(struct tty_driver));
- serial_driver.magic = TTY_DRIVER_MAGIC;
- serial_driver.driver_name = "wanpipe_tty";
- serial_driver.name = "ttyW";
- serial_driver.major = WAN_TTY_MAJOR;
- serial_driver.minor_start = WAN_TTY_MINOR;
- serial_driver.num = NR_PORTS;
- serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
- serial_driver.subtype = SERIAL_TYPE_NORMAL;
-
- serial_driver.init_termios = tty_std_termios;
- serial_driver.init_termios.c_cflag =
- B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- serial_driver.flags = TTY_DRIVER_REAL_RAW;
-
- serial_driver.refcount = &serial_refcount;
- serial_driver.table = serial_table;
- serial_driver.termios = serial_termios;
- serial_driver.termios_locked = serial_termios_locked;
- serial_driver.open = wanpipe_tty_open;
- serial_driver.close = wanpipe_tty_close;
- serial_driver.write = wanpipe_tty_write;
-
- serial_driver.put_char = wanpipe_tty_put_char;
- serial_driver.flush_chars = wanpipe_tty_flush_chars;
- serial_driver.write_room = wanpipe_tty_write_room;
- serial_driver.chars_in_buffer = wanpipe_tty_chars_in_buffer;
- serial_driver.flush_buffer = wanpipe_tty_flush_buffer;
- //serial_driver.ioctl = wanpipe_tty_ioctl;
- serial_driver.throttle = wanpipe_tty_throttle;
- serial_driver.unthrottle = wanpipe_tty_unthrottle;
- serial_driver.send_xchar = wanpipe_tty_send_xchar;
- serial_driver.set_termios = wanpipe_tty_set_termios;
- serial_driver.stop = wanpipe_tty_stop;
- serial_driver.start = wanpipe_tty_start;
- serial_driver.hangup = wanpipe_tty_hangup;
- serial_driver.break_ctl = wanpipe_tty_break;
- serial_driver.wait_until_sent = wanpipe_tty_wait_until_sent;
- serial_driver.read_proc = wanpipe_tty_read_proc;
-
- /*
- * The callout device is just like normal device except for
- * major number and the subtype code.
- */
- callout_driver = serial_driver;
- callout_driver.name = "cuw";
- callout_driver.major = TTYAUX_MAJOR;
- callout_driver.subtype = SERIAL_TYPE_CALLOUT;
- callout_driver.read_proc = 0;
- callout_driver.proc_entry = 0;
- if (tty_register_driver(&serial_driver)){
- printk(KERN_INFO "%s: Failed to register serial driver!n",
- card->devname);
- }
- if (tty_register_driver(&callout_driver)){
- printk(KERN_INFO "%s: Failed to register callout driver!n",
- card->devname);
- }
- }
- /* The subsequent ports must comply to the initial configuration */
- if (tty_driver_mode != card->u.c.async_mode){
- printk(KERN_INFO "%s: Error: TTY Driver operation mode mismatch!n",
- card->devname);
- printk(KERN_INFO "%s: The TTY driver is configured for %s!n",
- card->devname, tty_driver_mode ? "ASYNC" : "SYNC");
- return -EINVAL;
- }
-
- tty_init_cnt++;
-
- printk(KERN_INFO "%s: Initializing TTY %s Driver Minor %in",
- card->devname,
- tty_driver_mode ? "ASYNC" : "SYNC",
- card->tty_minor);
-
- tty_card_map[card->tty_minor] = card;
- state = &rs_table[card->tty_minor];
-
- state->magic = SSTATE_MAGIC;
- state->line = 0;
- state->type = PORT_UNKNOWN;
- state->custom_divisor = 0;
- state->close_delay = 5*HZ/10;
- state->closing_wait = 30*HZ;
- state->callout_termios = callout_driver.init_termios;
- state->normal_termios = serial_driver.init_termios;
- state->icount.cts = state->icount.dsr =
- state->icount.rng = state->icount.dcd = 0;
- state->icount.rx = state->icount.tx = 0;
- state->icount.frame = state->icount.parity = 0;
- state->icount.overrun = state->icount.brk = 0;
- state->irq = card->wandev.irq;
- card->tty_task_queue.routine = tty_poll_task;
- card->tty_task_queue.data = (void*)card;
- return 0;
- }
- #endif
- MODULE_LICENSE("GPL");
- /****** End ****************************************************************/