diff options
Diffstat (limited to 'ANDROID_3.4.5/drivers/tty/hvc/hvsi_lib.c')
-rw-r--r-- | ANDROID_3.4.5/drivers/tty/hvc/hvsi_lib.c | 426 |
1 files changed, 0 insertions, 426 deletions
diff --git a/ANDROID_3.4.5/drivers/tty/hvc/hvsi_lib.c b/ANDROID_3.4.5/drivers/tty/hvc/hvsi_lib.c deleted file mode 100644 index 6f4dd83d..00000000 --- a/ANDROID_3.4.5/drivers/tty/hvc/hvsi_lib.c +++ /dev/null @@ -1,426 +0,0 @@ -#include <linux/types.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/console.h> -#include <asm/hvsi.h> - -#include "hvc_console.h" - -static int hvsi_send_packet(struct hvsi_priv *pv, struct hvsi_header *packet) -{ - packet->seqno = atomic_inc_return(&pv->seqno); - - /* Assumes that always succeeds, works in practice */ - return pv->put_chars(pv->termno, (char *)packet, packet->len); -} - -static void hvsi_start_handshake(struct hvsi_priv *pv) -{ - struct hvsi_query q; - - /* Reset state */ - pv->established = 0; - atomic_set(&pv->seqno, 0); - - pr_devel("HVSI@%x: Handshaking started\n", pv->termno); - - /* Send version query */ - q.hdr.type = VS_QUERY_PACKET_HEADER; - q.hdr.len = sizeof(struct hvsi_query); - q.verb = VSV_SEND_VERSION_NUMBER; - hvsi_send_packet(pv, &q.hdr); -} - -static int hvsi_send_close(struct hvsi_priv *pv) -{ - struct hvsi_control ctrl; - - pv->established = 0; - - ctrl.hdr.type = VS_CONTROL_PACKET_HEADER; - ctrl.hdr.len = sizeof(struct hvsi_control); - ctrl.verb = VSV_CLOSE_PROTOCOL; - return hvsi_send_packet(pv, &ctrl.hdr); -} - -static void hvsi_cd_change(struct hvsi_priv *pv, int cd) -{ - if (cd) - pv->mctrl |= TIOCM_CD; - else { - pv->mctrl &= ~TIOCM_CD; - - /* We copy the existing hvsi driver semantics - * here which are to trigger a hangup when - * we get a carrier loss. - * Closing our connection to the server will - * do just that. - */ - if (!pv->is_console && pv->opened) { - pr_devel("HVSI@%x Carrier lost, hanging up !\n", - pv->termno); - hvsi_send_close(pv); - } - } -} - -static void hvsi_got_control(struct hvsi_priv *pv) -{ - struct hvsi_control *pkt = (struct hvsi_control *)pv->inbuf; - - switch (pkt->verb) { - case VSV_CLOSE_PROTOCOL: - /* We restart the handshaking */ - hvsi_start_handshake(pv); - break; - case VSV_MODEM_CTL_UPDATE: - /* Transition of carrier detect */ - hvsi_cd_change(pv, pkt->word & HVSI_TSCD); - break; - } -} - -static void hvsi_got_query(struct hvsi_priv *pv) -{ - struct hvsi_query *pkt = (struct hvsi_query *)pv->inbuf; - struct hvsi_query_response r; - - /* We only handle version queries */ - if (pkt->verb != VSV_SEND_VERSION_NUMBER) - return; - - pr_devel("HVSI@%x: Got version query, sending response...\n", - pv->termno); - - /* Send version response */ - r.hdr.type = VS_QUERY_RESPONSE_PACKET_HEADER; - r.hdr.len = sizeof(struct hvsi_query_response); - r.verb = VSV_SEND_VERSION_NUMBER; - r.u.version = HVSI_VERSION; - r.query_seqno = pkt->hdr.seqno; - hvsi_send_packet(pv, &r.hdr); - - /* Assume protocol is open now */ - pv->established = 1; -} - -static void hvsi_got_response(struct hvsi_priv *pv) -{ - struct hvsi_query_response *r = - (struct hvsi_query_response *)pv->inbuf; - - switch(r->verb) { - case VSV_SEND_MODEM_CTL_STATUS: - hvsi_cd_change(pv, r->u.mctrl_word & HVSI_TSCD); - pv->mctrl_update = 1; - break; - } -} - -static int hvsi_check_packet(struct hvsi_priv *pv) -{ - u8 len, type; - - /* Check header validity. If it's invalid, we ditch - * the whole buffer and hope we eventually resync - */ - if (pv->inbuf[0] < 0xfc) { - pv->inbuf_len = pv->inbuf_pktlen = 0; - return 0; - } - type = pv->inbuf[0]; - len = pv->inbuf[1]; - - /* Packet incomplete ? */ - if (pv->inbuf_len < len) - return 0; - - pr_devel("HVSI@%x: Got packet type %x len %d bytes:\n", - pv->termno, type, len); - - /* We have a packet, yay ! Handle it */ - switch(type) { - case VS_DATA_PACKET_HEADER: - pv->inbuf_pktlen = len - 4; - pv->inbuf_cur = 4; - return 1; - case VS_CONTROL_PACKET_HEADER: - hvsi_got_control(pv); - break; - case VS_QUERY_PACKET_HEADER: - hvsi_got_query(pv); - break; - case VS_QUERY_RESPONSE_PACKET_HEADER: - hvsi_got_response(pv); - break; - } - - /* Swallow packet and retry */ - pv->inbuf_len -= len; - memmove(pv->inbuf, &pv->inbuf[len], pv->inbuf_len); - return 1; -} - -static int hvsi_get_packet(struct hvsi_priv *pv) -{ - /* If we have room in the buffer, ask HV for more */ - if (pv->inbuf_len < HVSI_INBUF_SIZE) - pv->inbuf_len += pv->get_chars(pv->termno, - &pv->inbuf[pv->inbuf_len], - HVSI_INBUF_SIZE - pv->inbuf_len); - /* - * If we have at least 4 bytes in the buffer, check for - * a full packet and retry - */ - if (pv->inbuf_len >= 4) - return hvsi_check_packet(pv); - return 0; -} - -int hvsilib_get_chars(struct hvsi_priv *pv, char *buf, int count) -{ - unsigned int tries, read = 0; - - if (WARN_ON(!pv)) - return -ENXIO; - - /* If we aren't open, don't do anything in order to avoid races - * with connection establishment. The hvc core will call this - * before we have returned from notifier_add(), and we need to - * avoid multiple users playing with the receive buffer - */ - if (!pv->opened) - return 0; - - /* We try twice, once with what data we have and once more - * after we try to fetch some more from the hypervisor - */ - for (tries = 1; count && tries < 2; tries++) { - /* Consume existing data packet */ - if (pv->inbuf_pktlen) { - unsigned int l = min(count, (int)pv->inbuf_pktlen); - memcpy(&buf[read], &pv->inbuf[pv->inbuf_cur], l); - pv->inbuf_cur += l; - pv->inbuf_pktlen -= l; - count -= l; - read += l; - } - if (count == 0) - break; - - /* Data packet fully consumed, move down remaning data */ - if (pv->inbuf_cur) { - pv->inbuf_len -= pv->inbuf_cur; - memmove(pv->inbuf, &pv->inbuf[pv->inbuf_cur], - pv->inbuf_len); - pv->inbuf_cur = 0; - } - - /* Try to get another packet */ - if (hvsi_get_packet(pv)) - tries--; - } - if (!pv->established) { - pr_devel("HVSI@%x: returning -EPIPE\n", pv->termno); - return -EPIPE; - } - return read; -} - -int hvsilib_put_chars(struct hvsi_priv *pv, const char *buf, int count) -{ - struct hvsi_data dp; - int rc, adjcount = min(count, HVSI_MAX_OUTGOING_DATA); - - if (WARN_ON(!pv)) - return -ENODEV; - - dp.hdr.type = VS_DATA_PACKET_HEADER; - dp.hdr.len = adjcount + sizeof(struct hvsi_header); - memcpy(dp.data, buf, adjcount); - rc = hvsi_send_packet(pv, &dp.hdr); - if (rc <= 0) - return rc; - return adjcount; -} - -static void maybe_msleep(unsigned long ms) -{ - /* During early boot, IRQs are disabled, use mdelay */ - if (irqs_disabled()) - mdelay(ms); - else - msleep(ms); -} - -int hvsilib_read_mctrl(struct hvsi_priv *pv) -{ - struct hvsi_query q; - int rc, timeout; - - pr_devel("HVSI@%x: Querying modem control status...\n", - pv->termno); - - pv->mctrl_update = 0; - q.hdr.type = VS_QUERY_PACKET_HEADER; - q.hdr.len = sizeof(struct hvsi_query); - q.hdr.seqno = atomic_inc_return(&pv->seqno); - q.verb = VSV_SEND_MODEM_CTL_STATUS; - rc = hvsi_send_packet(pv, &q.hdr); - if (rc <= 0) { - pr_devel("HVSI@%x: Error %d...\n", pv->termno, rc); - return rc; - } - - /* Try for up to 200ms */ - for (timeout = 0; timeout < 20; timeout++) { - if (!pv->established) - return -ENXIO; - if (pv->mctrl_update) - return 0; - if (!hvsi_get_packet(pv)) - maybe_msleep(10); - } - return -EIO; -} - -int hvsilib_write_mctrl(struct hvsi_priv *pv, int dtr) -{ - struct hvsi_control ctrl; - unsigned short mctrl; - - mctrl = pv->mctrl; - if (dtr) - mctrl |= TIOCM_DTR; - else - mctrl &= ~TIOCM_DTR; - if (mctrl == pv->mctrl) - return 0; - pv->mctrl = mctrl; - - pr_devel("HVSI@%x: %s DTR...\n", pv->termno, - dtr ? "Setting" : "Clearing"); - - ctrl.hdr.type = VS_CONTROL_PACKET_HEADER, - ctrl.hdr.len = sizeof(struct hvsi_control); - ctrl.verb = VSV_SET_MODEM_CTL; - ctrl.mask = HVSI_TSDTR; - ctrl.word = dtr ? HVSI_TSDTR : 0; - return hvsi_send_packet(pv, &ctrl.hdr); -} - -void hvsilib_establish(struct hvsi_priv *pv) -{ - int timeout; - - pr_devel("HVSI@%x: Establishing...\n", pv->termno); - - /* Try for up to 200ms, there can be a packet to - * start the process waiting for us... - */ - for (timeout = 0; timeout < 20; timeout++) { - if (pv->established) - goto established; - if (!hvsi_get_packet(pv)) - maybe_msleep(10); - } - - /* Failed, send a close connection packet just - * in case - */ - pr_devel("HVSI@%x: ... sending close\n", pv->termno); - - hvsi_send_close(pv); - - /* Then restart handshake */ - - pr_devel("HVSI@%x: ... restarting handshake\n", pv->termno); - - hvsi_start_handshake(pv); - - pr_devel("HVSI@%x: ... waiting handshake\n", pv->termno); - - /* Try for up to 200s */ - for (timeout = 0; timeout < 20; timeout++) { - if (pv->established) - goto established; - if (!hvsi_get_packet(pv)) - maybe_msleep(10); - } - - if (!pv->established) { - pr_devel("HVSI@%x: Timeout handshaking, giving up !\n", - pv->termno); - return; - } - established: - /* Query modem control lines */ - - pr_devel("HVSI@%x: ... established, reading mctrl\n", pv->termno); - - hvsilib_read_mctrl(pv); - - /* Set our own DTR */ - - pr_devel("HVSI@%x: ... setting mctrl\n", pv->termno); - - hvsilib_write_mctrl(pv, 1); - - /* Set the opened flag so reads are allowed */ - wmb(); - pv->opened = 1; -} - -int hvsilib_open(struct hvsi_priv *pv, struct hvc_struct *hp) -{ - pr_devel("HVSI@%x: open !\n", pv->termno); - - /* Keep track of the tty data structure */ - pv->tty = tty_kref_get(hp->tty); - - hvsilib_establish(pv); - - return 0; -} - -void hvsilib_close(struct hvsi_priv *pv, struct hvc_struct *hp) -{ - unsigned long flags; - - pr_devel("HVSI@%x: close !\n", pv->termno); - - if (!pv->is_console) { - pr_devel("HVSI@%x: Not a console, tearing down\n", - pv->termno); - - /* Clear opened, synchronize with khvcd */ - spin_lock_irqsave(&hp->lock, flags); - pv->opened = 0; - spin_unlock_irqrestore(&hp->lock, flags); - - /* Clear our own DTR */ - if (!pv->tty || (pv->tty->termios->c_cflag & HUPCL)) - hvsilib_write_mctrl(pv, 0); - - /* Tear down the connection */ - hvsi_send_close(pv); - } - - if (pv->tty) - tty_kref_put(pv->tty); - pv->tty = NULL; -} - -void hvsilib_init(struct hvsi_priv *pv, - int (*get_chars)(uint32_t termno, char *buf, int count), - int (*put_chars)(uint32_t termno, const char *buf, - int count), - int termno, int is_console) -{ - memset(pv, 0, sizeof(*pv)); - pv->get_chars = get_chars; - pv->put_chars = put_chars; - pv->termno = termno; - pv->is_console = is_console; -} |