Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * linux/drivers/acorn/scsi/msgqueue.c | |
3 | * | |
4 | * Copyright (C) 1997-1998 Russell King | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License version 2 as | |
8 | * published by the Free Software Foundation. | |
9 | * | |
10 | * message queue handling | |
11 | */ | |
12 | #include <linux/module.h> | |
13 | #include <linux/kernel.h> | |
14 | #include <linux/stddef.h> | |
15 | #include <linux/init.h> | |
16 | ||
17 | #include "msgqueue.h" | |
18 | ||
19 | /* | |
20 | * Function: struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq) | |
21 | * Purpose : Allocate a message queue entry | |
22 | * Params : msgq - message queue to claim entry for | |
23 | * Returns : message queue entry or NULL. | |
24 | */ | |
25 | static struct msgqueue_entry *mqe_alloc(MsgQueue_t *msgq) | |
26 | { | |
27 | struct msgqueue_entry *mq; | |
28 | ||
29 | if ((mq = msgq->free) != NULL) | |
30 | msgq->free = mq->next; | |
31 | ||
32 | return mq; | |
33 | } | |
34 | ||
35 | /* | |
36 | * Function: void mqe_free(MsgQueue_t *msgq, struct msgqueue_entry *mq) | |
37 | * Purpose : free a message queue entry | |
38 | * Params : msgq - message queue to free entry from | |
39 | * mq - message queue entry to free | |
40 | */ | |
41 | static void mqe_free(MsgQueue_t *msgq, struct msgqueue_entry *mq) | |
42 | { | |
43 | if (mq) { | |
44 | mq->next = msgq->free; | |
45 | msgq->free = mq; | |
46 | } | |
47 | } | |
48 | ||
49 | /* | |
50 | * Function: void msgqueue_initialise(MsgQueue_t *msgq) | |
51 | * Purpose : initialise a message queue | |
52 | * Params : msgq - queue to initialise | |
53 | */ | |
54 | void msgqueue_initialise(MsgQueue_t *msgq) | |
55 | { | |
56 | int i; | |
57 | ||
58 | msgq->qe = NULL; | |
59 | msgq->free = &msgq->entries[0]; | |
60 | ||
61 | for (i = 0; i < NR_MESSAGES; i++) | |
62 | msgq->entries[i].next = &msgq->entries[i + 1]; | |
63 | ||
64 | msgq->entries[NR_MESSAGES - 1].next = NULL; | |
65 | } | |
66 | ||
67 | ||
68 | /* | |
69 | * Function: void msgqueue_free(MsgQueue_t *msgq) | |
70 | * Purpose : free a queue | |
71 | * Params : msgq - queue to free | |
72 | */ | |
73 | void msgqueue_free(MsgQueue_t *msgq) | |
74 | { | |
75 | } | |
76 | ||
77 | /* | |
78 | * Function: int msgqueue_msglength(MsgQueue_t *msgq) | |
79 | * Purpose : calculate the total length of all messages on the message queue | |
80 | * Params : msgq - queue to examine | |
81 | * Returns : number of bytes of messages in queue | |
82 | */ | |
83 | int msgqueue_msglength(MsgQueue_t *msgq) | |
84 | { | |
85 | struct msgqueue_entry *mq = msgq->qe; | |
86 | int length = 0; | |
87 | ||
88 | for (mq = msgq->qe; mq; mq = mq->next) | |
89 | length += mq->msg.length; | |
90 | ||
91 | return length; | |
92 | } | |
93 | ||
94 | /* | |
95 | * Function: struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno) | |
96 | * Purpose : return a message | |
97 | * Params : msgq - queue to obtain message from | |
98 | * : msgno - message number | |
99 | * Returns : pointer to message string, or NULL | |
100 | */ | |
101 | struct message *msgqueue_getmsg(MsgQueue_t *msgq, int msgno) | |
102 | { | |
103 | struct msgqueue_entry *mq; | |
104 | ||
105 | for (mq = msgq->qe; mq && msgno; mq = mq->next, msgno--); | |
106 | ||
107 | return mq ? &mq->msg : NULL; | |
108 | } | |
109 | ||
110 | /* | |
111 | * Function: int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...) | |
112 | * Purpose : add a message onto a message queue | |
113 | * Params : msgq - queue to add message on | |
114 | * length - length of message | |
115 | * ... - message bytes | |
116 | * Returns : != 0 if successful | |
117 | */ | |
118 | int msgqueue_addmsg(MsgQueue_t *msgq, int length, ...) | |
119 | { | |
120 | struct msgqueue_entry *mq = mqe_alloc(msgq); | |
121 | va_list ap; | |
122 | ||
123 | if (mq) { | |
124 | struct msgqueue_entry **mqp; | |
125 | int i; | |
126 | ||
127 | va_start(ap, length); | |
128 | for (i = 0; i < length; i++) | |
129 | mq->msg.msg[i] = va_arg(ap, unsigned int); | |
130 | va_end(ap); | |
131 | ||
132 | mq->msg.length = length; | |
133 | mq->msg.fifo = 0; | |
134 | mq->next = NULL; | |
135 | ||
136 | mqp = &msgq->qe; | |
137 | while (*mqp) | |
138 | mqp = &(*mqp)->next; | |
139 | ||
140 | *mqp = mq; | |
141 | } | |
142 | ||
143 | return mq != NULL; | |
144 | } | |
145 | ||
146 | /* | |
147 | * Function: void msgqueue_flush(MsgQueue_t *msgq) | |
148 | * Purpose : flush all messages from message queue | |
149 | * Params : msgq - queue to flush | |
150 | */ | |
151 | void msgqueue_flush(MsgQueue_t *msgq) | |
152 | { | |
153 | struct msgqueue_entry *mq, *mqnext; | |
154 | ||
155 | for (mq = msgq->qe; mq; mq = mqnext) { | |
156 | mqnext = mq->next; | |
157 | mqe_free(msgq, mq); | |
158 | } | |
159 | msgq->qe = NULL; | |
160 | } | |
161 | ||
162 | EXPORT_SYMBOL(msgqueue_initialise); | |
163 | EXPORT_SYMBOL(msgqueue_free); | |
164 | EXPORT_SYMBOL(msgqueue_msglength); | |
165 | EXPORT_SYMBOL(msgqueue_getmsg); | |
166 | EXPORT_SYMBOL(msgqueue_addmsg); | |
167 | EXPORT_SYMBOL(msgqueue_flush); | |
168 | ||
169 | MODULE_AUTHOR("Russell King"); | |
170 | MODULE_DESCRIPTION("SCSI message queue handling"); | |
171 | MODULE_LICENSE("GPL"); |