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