OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [armnommu/] [drivers/] [scsi/] [queue_mod.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 * queue.c: queue handling primitives
3
 *
4
 * (c) 1997 Russell King
5
 *
6
 * Changelog:
7
 *  15-Sep-1997 RMK     Created.
8
 *  11-Oct-1997 RMK     Corrected problem with queue_remove_exclude
9
 *                      not updating internal linked list properly
10
 *                      (was causing commands to go missing).
11
 */
12
 
13
#define SECTOR_SIZE 512
14
 
15
#define __NO_VERSION__
16
 
17
#include <linux/module.h>
18
#include <linux/blk.h>
19
#include <linux/kernel.h>
20
#include <linux/string.h>
21
#include <linux/malloc.h>
22
 
23
#include "scsi.h"
24
 
25
typedef struct queue_entry {
26
        struct queue_entry *next;
27
        struct queue_entry *prev;
28
        unsigned long      magic;
29
        Scsi_Cmnd          *SCpnt;
30
} QE_t;
31
 
32
#define QUEUE_MAGIC_FREE        0xf7e1c9a3
33
#define QUEUE_MAGIC_USED        0xf7e1cc33
34
 
35
#include "queue.h"
36
 
37
/*
38
 * Function: void queue_initialise (Queue_t *queue)
39
 * Purpose : initialise a queue
40
 * Params  : queue - queue to initialise
41
 */
42
int queue_initialise (Queue_t *queue)
43
{
44
        unsigned int nqueues;
45
        QE_t *q;
46
 
47
        queue->alloc = queue->free = q = (QE_t *) kmalloc (SECTOR_SIZE, GFP_KERNEL);
48
        if (q) {
49
                nqueues = SECTOR_SIZE / sizeof (QE_t);
50
 
51
                for (; nqueues; q++, nqueues--) {
52
                        q->next = q + 1;
53
                        q->prev = NULL;
54
                        q->magic = QUEUE_MAGIC_FREE;
55
                        q->SCpnt = NULL;
56
                }
57
                q -= 1;
58
                q->next = NULL;
59
        }
60
 
61
        return q != NULL;
62
}
63
 
64
/*
65
 * Function: void queue_free (Queue_t *queue)
66
 * Purpose : free a queue
67
 * Params  : queue - queue to free
68
 */
69
void queue_free (Queue_t *queue)
70
{
71
        if (queue->alloc)
72
                kfree (queue->alloc);
73
}
74
 
75
 
76
/*
77
 * Function: int queue_add_cmd_ordered (Queue_t *queue, Scsi_Cmnd *SCpnt)
78
 * Purpose : Add a new command onto a queue, adding REQUEST_SENSE to head.
79
 * Params  : queue - destination queue
80
 *           SCpnt - command to add
81
 * Returns : 0 on error, !0 on success
82
 */
83
int queue_add_cmd_ordered (Queue_t *queue, Scsi_Cmnd *SCpnt)
84
{
85
        unsigned long flags;
86
        QE_t *q;
87
 
88
        save_flags_cli (flags);
89
        q = queue->free;
90
        if (q)
91
                queue->free = q->next;
92
 
93
        if (q) {
94
                if (q->magic != QUEUE_MAGIC_FREE) {
95
                        restore_flags (flags);
96
                        panic ("scsi queues corrupted - queue entry %p not free", q);
97
                }
98
 
99
                q->magic = QUEUE_MAGIC_USED;
100
                q->SCpnt = SCpnt;
101
 
102
                if (SCpnt->cmnd[0] == REQUEST_SENSE) { /* request_sense gets put on the queue head */
103
                        if (queue->head) {
104
                                q->prev = NULL;
105
                                q->next = queue->head;
106
                                queue->head->prev = q;
107
                                queue->head = q;
108
                        } else {
109
                                q->next = q->prev = NULL;
110
                                queue->head = queue->tail = q;
111
                        }
112
                } else {                                /* others get put on the tail */
113
                        if (queue->tail) {
114
                                q->next = NULL;
115
                                q->prev = queue->tail;
116
                                queue->tail->next = q;
117
                                queue->tail = q;
118
                        } else {
119
                                q->next = q->prev = NULL;
120
                                queue->head = queue->tail = q;
121
                        }
122
                }
123
        }
124
        restore_flags (flags);
125
 
126
        return q != NULL;
127
}
128
 
129
/*
130
 * Function: int queue_add_cmd_tail (Queue_t *queue, Scsi_Cmnd *SCpnt)
131
 * Purpose : Add a new command onto a queue, adding onto tail of list
132
 * Params  : queue - destination queue
133
 *           SCpnt - command to add
134
 * Returns : 0 on error, !0 on success
135
 */
136
int queue_add_cmd_tail (Queue_t *queue, Scsi_Cmnd *SCpnt)
137
{
138
        unsigned long flags;
139
        QE_t *q;
140
 
141
        save_flags_cli (flags);
142
        q = queue->free;
143
        if (q)
144
                queue->free = q->next;
145
 
146
        if (q) {
147
                if (q->magic != QUEUE_MAGIC_FREE) {
148
                        restore_flags (flags);
149
                        panic ("scsi queues corrupted - queue entry %p not free", q);
150
                }
151
 
152
                q->magic = QUEUE_MAGIC_USED;
153
                q->SCpnt = SCpnt;
154
 
155
                if (queue->tail) {
156
                        q->next = NULL;
157
                        q->prev = queue->tail;
158
                        queue->tail->next = q;
159
                        queue->tail = q;
160
                } else {
161
                        q->next = q->prev = NULL;
162
                        queue->head = queue->tail = q;
163
                }
164
        }
165
        restore_flags (flags);
166
 
167
        return q != NULL;
168
}
169
 
170
/*
171
 * Function: Scsi_Cmnd *queue_remove_exclude (queue, exclude)
172
 * Purpose : remove a SCSI command from a queue
173
 * Params  : queue   - queue to remove command from
174
 *           exclude - bit array of target&lun which is busy
175
 * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
176
 */
177
Scsi_Cmnd *queue_remove_exclude (Queue_t *queue, unsigned char *exclude)
178
{
179
        unsigned long flags;
180
        Scsi_Cmnd *SCpnt;
181
        QE_t *q, *prev;
182
 
183
        save_flags_cli (flags);
184
        for (q = queue->head, prev = NULL; q; q = q->next) {
185
                if (exclude && !test_bit (q->SCpnt->target * 8 + q->SCpnt->lun, exclude))
186
                        break;
187
                prev = q;
188
        }
189
 
190
        if (q) {
191
                if (q->magic != QUEUE_MAGIC_USED) {
192
                        restore_flags (flags);
193
                        panic ("q_remove_exclude: scsi queues corrupted - queue entry not used");
194
                }
195
                if (q->prev != prev)
196
                        panic ("q_remove_exclude: scsi queues corrupted - q->prev != prev");
197
 
198
                if (!prev) {
199
                        queue->head = q->next;
200
                        if (queue->head)
201
                                queue->head->prev = NULL;
202
                        else
203
                                queue->tail = NULL;
204
                } else {
205
                        prev->next = q->next;
206
                        if (prev->next)
207
                                prev->next->prev = prev;
208
                        else
209
                                queue->tail = prev;
210
                }
211
 
212
                SCpnt = q->SCpnt;
213
 
214
                q->next = queue->free;
215
                queue->free = q;
216
                q->magic = QUEUE_MAGIC_FREE;
217
        } else
218
                SCpnt = NULL;
219
 
220
        restore_flags (flags);
221
 
222
        return SCpnt;
223
}
224
 
225
/*
226
 * Function: Scsi_Cmnd *queue_remove (queue)
227
 * Purpose : removes first SCSI command from a queue
228
 * Params  : queue   - queue to remove command from
229
 * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
230
 */
231
Scsi_Cmnd *queue_remove (Queue_t *queue)
232
{
233
        unsigned long flags;
234
        Scsi_Cmnd *SCpnt;
235
        QE_t *q;
236
 
237
        save_flags_cli (flags);
238
        q = queue->head;
239
        if (q) {
240
                queue->head = q->next;
241
                if (queue->head)
242
                        queue->head->prev = NULL;
243
                else
244
                        queue->tail = NULL;
245
 
246
                if (q->magic != QUEUE_MAGIC_USED) {
247
                        restore_flags (flags);
248
                        panic ("scsi queues corrupted - queue entry not used");
249
                }
250
 
251
                SCpnt = q->SCpnt;
252
 
253
                q->next = queue->free;
254
                queue->free = q;
255
                q->magic = QUEUE_MAGIC_FREE;
256
        } else
257
                SCpnt = NULL;
258
 
259
        restore_flags (flags);
260
 
261
        return SCpnt;
262
}
263
 
264
/*
265
 * Function: Scsi_Cmnd *queue_remove_tgtluntag (queue, target, lun, tag)
266
 * Purpose : remove a SCSI command from the queue for a specified target/lun/tag
267
 * Params  : queue  - queue to remove command from
268
 *           target - target that we want
269
 *           lun    - lun on device
270
 *           tag    - tag on device
271
 * Returns : Scsi_Cmnd if successful, or NULL if no command satisfies requirements
272
 */
273
Scsi_Cmnd *queue_remove_tgtluntag (Queue_t *queue, int target, int lun, int tag)
274
{
275
        unsigned long flags;
276
        Scsi_Cmnd *SCpnt;
277
        QE_t *q, *prev;
278
 
279
        save_flags_cli (flags);
280
        for (q = queue->head, prev = NULL; q; q = q->next) {
281
                if (q->SCpnt->target == target &&
282
                    q->SCpnt->lun == lun &&
283
                    q->SCpnt->tag == tag)
284
                        break;
285
 
286
                prev = q;
287
        }
288
 
289
        if (q) {
290
                if (q->magic != QUEUE_MAGIC_USED) {
291
                        restore_flags (flags);
292
                        panic ("q_remove_tgtluntag: scsi queues corrupted - queue entry not used");
293
                }
294
                if (q->prev != prev)
295
                        panic ("q_remove_tgtluntag: scsi queues corrupted - q->prev != prev");
296
 
297
                if (!prev) {
298
                        queue->head = q->next;
299
                        if (queue->head)
300
                                queue->head->prev = NULL;
301
                        else
302
                                queue->tail = NULL;
303
                } else {
304
                        prev->next = q->next;
305
                        if (prev->next)
306
                                prev->next->prev = prev;
307
                        else
308
                                queue->tail = prev;
309
                }
310
 
311
                SCpnt = q->SCpnt;
312
 
313
                q->magic = QUEUE_MAGIC_FREE;
314
                q->next = queue->free;
315
                queue->free = q;
316
        } else
317
                SCpnt = NULL;
318
 
319
        restore_flags (flags);
320
 
321
        return SCpnt;
322
}
323
 
324
/*
325
 * Function: int queue_probetgtlun (queue, target, lun)
326
 * Purpose : check to see if we have a command in the queue for the specified
327
 *           target/lun.
328
 * Params  : queue  - queue to look in
329
 *           target - target we want to probe
330
 *           lun    - lun on target
331
 * Returns : 0 if not found, != 0 if found
332
 */
333
int queue_probetgtlun (Queue_t *queue, int target, int lun)
334
{
335
        QE_t *q;
336
 
337
        for (q = queue->head; q; q = q->next)
338
                if (q->SCpnt->target == target &&
339
                    q->SCpnt->lun == lun)
340
                        break;
341
 
342
        return q != NULL;
343
}
344
 
345
/*
346
 * Function: int queue_cmdonqueue (queue, SCpnt)
347
 * Purpose : check to see if we have a command on the queue
348
 * Params  : queue - queue to look in
349
 *           SCpnt - command to find
350
 * Returns : 0 if not found, != 0 if found
351
 */
352
int queue_cmdonqueue (Queue_t *queue, Scsi_Cmnd *SCpnt)
353
{
354
        QE_t *q;
355
 
356
        for (q = queue->head; q; q = q->next)
357
                if (q->SCpnt == SCpnt)
358
                        break;
359
 
360
        return q != NULL;
361
}
362
 
363
/*
364
 * Function: int queue_removecmd (Queue_t *queue, Scsi_Cmnd *SCpnt)
365
 * Purpose : remove a specific command from the queues
366
 * Params  : queue - queue to look in
367
 *           SCpnt - command to find
368
 * Returns : 0 if not found
369
 */
370
int queue_removecmd (Queue_t *queue, Scsi_Cmnd *SCpnt)
371
{
372
        unsigned long flags;
373
        QE_t *q, *prev;
374
 
375
        save_flags_cli (flags);
376
        for (q = queue->head, prev = NULL; q; q = q->next) {
377
                if (q->SCpnt == SCpnt)
378
                        break;
379
 
380
                prev = q;
381
        }
382
 
383
        if (q) {
384
                if (q->magic != QUEUE_MAGIC_USED) {
385
                        restore_flags (flags);
386
                        panic ("q_removecmd: scsi queues corrupted - queue entry not used");
387
                }
388
                if (q->prev != prev)
389
                        panic ("q_removecmd: scsi queues corrupted - q->prev != prev");
390
 
391
                if (!prev) {
392
                        queue->head = q->next;
393
                        if (queue->head)
394
                                queue->head->prev = NULL;
395
                        else
396
                                queue->tail = NULL;
397
                } else {
398
                        prev->next = q->next;
399
                        if (prev->next)
400
                                prev->next->prev = prev;
401
                        else
402
                                queue->tail = prev;
403
                }
404
 
405
                q->magic = QUEUE_MAGIC_FREE;
406
                q->next = queue->free;
407
                queue->free = q;
408
        }
409
 
410
        restore_flags (flags);
411
 
412
        return q != NULL;
413
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.