/* * message.c * Copyright (C) 1997-2000 SpellCaster Telecommunications Inc. * $Id: message.c,v 1.1 2004/03/11 03:59:31 bcrl Exp $ * Released under the GNU Public License. See LICENSE file for details. */ #define __KERNEL__ #include "includes.h" #include "message.h" #include "adapter.h" unsigned int send_message(adapter_t *a, __u16 proc_id, __u8 process, __u8 type, void *data, __u8 len) { message_t *m = (message_t *)(a->vrambase + a->r->cmd_write_ptr); /* The sequence number must not be 0 */ m->seq_no = a->tx_seqno++; if(m->seq_no == 0) m->seq_no = a->tx_seqno++; m->proc_id = proc_id; m->process = process; m->type = type; if(len > 22) { /* Error */ return 0; } m->count = len + 1; if(len > 0) memcpy(m->u.raw, data, len); a->r->cmd_write_ptr = 0x1000 + (((a->r->cmd_write_ptr - 0x1000) + sizeof(message_t)) & 0x3FFF); return m->seq_no; } response_t *receive_message(adapter_t *a) { response_t *m = (response_t *)(a->vrambase + a->r->rsp_read_ptr); if(a->r->rsp_read_ptr == a->r->rsp_write_ptr) return NULL; a->r->rsp_read_ptr = 0x5000 + (((a->r->rsp_read_ptr - 0x5000) + sizeof(message_t)) & 0x3FFF); return m; } struct sr_timeout_d { bool timed_out; struct wait_queue **wake; }; static void sr_timeout(unsigned long data) { struct sr_timeout_d *foo = (struct sr_timeout_d *)data; foo->timed_out = true; wake_up(foo->wake); } response_t *sendrcv_message(adapter_t *a, __u16 proc_id, __u8 process, __u8 type, void *data, __u8 len, int timeout) { struct sr_timeout_d td; struct timer_list timer; if(a->async_seq != ~0) { pr_debug("%s: Only one async message at a time pls!\n", a->devicename); return NULL; } if((a->async_seq = send_message(a, proc_id, process, type, data, len)) == 0){ pr_debug("%s: Zero seqno\n", a->devicename); a->async_seq = ~0; return NULL; } /* Set the timeout timer */ init_timer(&timer); td.timed_out = false; td.wake = &a->async_queue; timer.data = (unsigned long) &td; timer.function = sr_timeout; timer.expires = jiffies + (HZ * timeout); add_timer(&timer); /* Wait for something to happen */ sleep_on(&a->async_queue); /* Clear the timer */ del_timer(&timer); /* The timer fired */ if(td.timed_out) { a->async_seq = ~0; return NULL; } /* Error response */ if(((response_t *)a->async_rsp)->type == 0x0e) { printk(KERN_ERR "%s: Message error code == %d, cmd == %d\n", a->devicename, ((response_t *)a->async_rsp)->u.error.diag_code, ((response_t *)a->async_rsp)->u.error.command); return NULL; } return a->async_rsp; }