linux/drivers/isdn/sc/message.c
<<
>>
Prefs
   1/* $Id: message.c,v 1.5.8.2 2001/09/23 22:24:59 kai Exp $
   2 *
   3 * functions for sending and receiving control messages
   4 *
   5 * Copyright (C) 1996  SpellCaster Telecommunications Inc.
   6 *
   7 * This software may be used and distributed according to the terms
   8 * of the GNU General Public License, incorporated herein by reference.
   9 *
  10 * For more information, please contact gpl-info@spellcast.com or write:
  11 *
  12 *     SpellCaster Telecommunications Inc.
  13 *     5621 Finch Avenue East, Unit #3
  14 *     Scarborough, Ontario  Canada
  15 *     M1B 2T9
  16 *     +1 (416) 297-8565
  17 *     +1 (416) 297-6433 Facsimile
  18 */
  19#include <linux/sched.h>
  20#include "includes.h"
  21#include "hardware.h"
  22#include "message.h"
  23#include "card.h"
  24
  25/*
  26 * receive a message from the board
  27 */
  28int receivemessage(int card, RspMessage *rspmsg)
  29{
  30        DualPortMemory *dpm;
  31        unsigned long flags;
  32
  33        if (!IS_VALID_CARD(card)) {
  34                pr_debug("Invalid param: %d is not a valid card id\n", card);
  35                return -EINVAL;
  36        }
  37
  38        pr_debug("%s: Entered receivemessage\n",
  39                 sc_adapter[card]->devicename);
  40
  41        /*
  42         * See if there are messages waiting
  43         */
  44        if (inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) {
  45                /*
  46                 * Map in the DPM to the base page and copy the message
  47                 */
  48                spin_lock_irqsave(&sc_adapter[card]->lock, flags);
  49                outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
  50                     sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
  51                dpm = (DualPortMemory *) sc_adapter[card]->rambase;
  52                memcpy_fromio(rspmsg, &(dpm->rsp_queue[dpm->rsp_tail]),
  53                              MSG_LEN);
  54                dpm->rsp_tail = (dpm->rsp_tail + 1) % MAX_MESSAGES;
  55                inb(sc_adapter[card]->ioport[FIFO_READ]);
  56                spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
  57                /*
  58                 * Tell the board that the message is received
  59                 */
  60                pr_debug("%s: Received Message seq:%d pid:%d time:%d cmd:%d "
  61                         "cnt:%d (type,class,code):(%d,%d,%d) "
  62                         "link:%d stat:0x%x\n",
  63                         sc_adapter[card]->devicename,
  64                         rspmsg->sequence_no,
  65                         rspmsg->process_id,
  66                         rspmsg->time_stamp,
  67                         rspmsg->cmd_sequence_no,
  68                         rspmsg->msg_byte_cnt,
  69                         rspmsg->type,
  70                         rspmsg->class,
  71                         rspmsg->code,
  72                         rspmsg->phy_link_no,
  73                         rspmsg->rsp_status);
  74
  75                return 0;
  76        }
  77        return -ENOMSG;
  78}
  79
  80/*
  81 * send a message to the board
  82 */
  83int sendmessage(int card,
  84                unsigned int procid,
  85                unsigned int type,
  86                unsigned int class,
  87                unsigned int code,
  88                unsigned int link,
  89                unsigned int data_len,
  90                unsigned int *data)
  91{
  92        DualPortMemory *dpm;
  93        ReqMessage sndmsg;
  94        unsigned long flags;
  95
  96        if (!IS_VALID_CARD(card)) {
  97                pr_debug("Invalid param: %d is not a valid card id\n", card);
  98                return -EINVAL;
  99        }
 100
 101        /*
 102         * Make sure we only send CEPID messages when the engine is up
 103         * and CMPID messages when it is down
 104         */
 105        if (sc_adapter[card]->EngineUp && procid == CMPID) {
 106                pr_debug("%s: Attempt to send CM message with engine up\n",
 107                         sc_adapter[card]->devicename);
 108                return -ESRCH;
 109        }
 110
 111        if (!sc_adapter[card]->EngineUp && procid == CEPID) {
 112                pr_debug("%s: Attempt to send CE message with engine down\n",
 113                         sc_adapter[card]->devicename);
 114                return -ESRCH;
 115        }
 116
 117        memset(&sndmsg, 0, MSG_LEN);
 118        sndmsg.msg_byte_cnt = 4;
 119        sndmsg.type = type;
 120        sndmsg.class = class;
 121        sndmsg.code = code;
 122        sndmsg.phy_link_no = link;
 123
 124        if (data_len > 0) {
 125                if (data_len > MSG_DATA_LEN)
 126                        data_len = MSG_DATA_LEN;
 127                memcpy(&(sndmsg.msg_data), data, data_len);
 128                sndmsg.msg_byte_cnt = data_len + 8;
 129        }
 130
 131        sndmsg.process_id = procid;
 132        sndmsg.sequence_no = sc_adapter[card]->seq_no++ % 256;
 133
 134        /*
 135         * wait for an empty slot in the queue
 136         */
 137        while (!(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & WF_NOT_FULL))
 138                udelay(1);
 139
 140        /*
 141         * Disable interrupts and map in shared memory
 142         */
 143        spin_lock_irqsave(&sc_adapter[card]->lock, flags);
 144        outb((sc_adapter[card]->shmem_magic >> 14) | 0x80,
 145             sc_adapter[card]->ioport[sc_adapter[card]->shmem_pgport]);
 146        dpm = (DualPortMemory *) sc_adapter[card]->rambase;     /* Fix me */
 147        memcpy_toio(&(dpm->req_queue[dpm->req_head]), &sndmsg, MSG_LEN);
 148        dpm->req_head = (dpm->req_head + 1) % MAX_MESSAGES;
 149        outb(sndmsg.sequence_no, sc_adapter[card]->ioport[FIFO_WRITE]);
 150        spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 151
 152        pr_debug("%s: Sent Message seq:%d pid:%d time:%d "
 153                 "cnt:%d (type,class,code):(%d,%d,%d) "
 154                 "link:%d\n ",
 155                 sc_adapter[card]->devicename,
 156                 sndmsg.sequence_no,
 157                 sndmsg.process_id,
 158                 sndmsg.time_stamp,
 159                 sndmsg.msg_byte_cnt,
 160                 sndmsg.type,
 161                 sndmsg.class,
 162                 sndmsg.code,
 163                 sndmsg.phy_link_no);
 164
 165        return 0;
 166}
 167
 168int send_and_receive(int card,
 169                     unsigned int procid,
 170                     unsigned char type,
 171                     unsigned char class,
 172                     unsigned char code,
 173                     unsigned char link,
 174                     unsigned char data_len,
 175                     unsigned char *data,
 176                     RspMessage *mesgdata,
 177                     int timeout)
 178{
 179        int retval;
 180        int tries;
 181
 182        if (!IS_VALID_CARD(card)) {
 183                pr_debug("Invalid param: %d is not a valid card id\n", card);
 184                return -EINVAL;
 185        }
 186
 187        sc_adapter[card]->want_async_messages = 1;
 188        retval = sendmessage(card, procid, type, class, code, link,
 189                             data_len, (unsigned int *) data);
 190
 191        if (retval) {
 192                pr_debug("%s: SendMessage failed in SAR\n",
 193                         sc_adapter[card]->devicename);
 194                sc_adapter[card]->want_async_messages = 0;
 195                return -EIO;
 196        }
 197
 198        tries = 0;
 199        /* wait for the response */
 200        while (tries < timeout) {
 201                schedule_timeout_interruptible(1);
 202
 203                pr_debug("SAR waiting..\n");
 204
 205                /*
 206                 * See if we got our message back
 207                 */
 208                if ((sc_adapter[card]->async_msg.type == type) &&
 209                    (sc_adapter[card]->async_msg.class == class) &&
 210                    (sc_adapter[card]->async_msg.code == code) &&
 211                    (sc_adapter[card]->async_msg.phy_link_no == link)) {
 212
 213                        /*
 214                         * Got it!
 215                         */
 216                        pr_debug("%s: Got ASYNC message\n",
 217                                 sc_adapter[card]->devicename);
 218                        memcpy(mesgdata, &(sc_adapter[card]->async_msg),
 219                               sizeof(RspMessage));
 220                        sc_adapter[card]->want_async_messages = 0;
 221                        return 0;
 222                }
 223
 224                tries++;
 225        }
 226
 227        pr_debug("%s: SAR message timeout\n", sc_adapter[card]->devicename);
 228        sc_adapter[card]->want_async_messages = 0;
 229        return -ETIME;
 230}
 231