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

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [armnommu/] [drivers/] [scsi/] [queue_mod.c] - Diff between revs 1765 and 1782

Only display areas with differences | Details | Blame | View Log

Rev 1765 Rev 1782
/*
/*
 * queue.c: queue handling primitives
 * queue.c: queue handling primitives
 *
 *
 * (c) 1997 Russell King
 * (c) 1997 Russell King
 *
 *
 * Changelog:
 * Changelog:
 *  15-Sep-1997 RMK     Created.
 *  15-Sep-1997 RMK     Created.
 *  11-Oct-1997 RMK     Corrected problem with queue_remove_exclude
 *  11-Oct-1997 RMK     Corrected problem with queue_remove_exclude
 *                      not updating internal linked list properly
 *                      not updating internal linked list properly
 *                      (was causing commands to go missing).
 *                      (was causing commands to go missing).
 */
 */
 
 
#define SECTOR_SIZE 512
#define SECTOR_SIZE 512
 
 
#define __NO_VERSION__
#define __NO_VERSION__
 
 
#include <linux/module.h>
#include <linux/module.h>
#include <linux/blk.h>
#include <linux/blk.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/malloc.h>
#include <linux/malloc.h>
 
 
#include "scsi.h"
#include "scsi.h"
 
 
typedef struct queue_entry {
typedef struct queue_entry {
        struct queue_entry *next;
        struct queue_entry *next;
        struct queue_entry *prev;
        struct queue_entry *prev;
        unsigned long      magic;
        unsigned long      magic;
        Scsi_Cmnd          *SCpnt;
        Scsi_Cmnd          *SCpnt;
} QE_t;
} QE_t;
 
 
#define QUEUE_MAGIC_FREE        0xf7e1c9a3
#define QUEUE_MAGIC_FREE        0xf7e1c9a3
#define QUEUE_MAGIC_USED        0xf7e1cc33
#define QUEUE_MAGIC_USED        0xf7e1cc33
 
 
#include "queue.h"
#include "queue.h"
 
 
/*
/*
 * Function: void queue_initialise (Queue_t *queue)
 * Function: void queue_initialise (Queue_t *queue)
 * Purpose : initialise a queue
 * Purpose : initialise a queue
 * Params  : queue - queue to initialise
 * Params  : queue - queue to initialise
 */
 */
int queue_initialise (Queue_t *queue)
int queue_initialise (Queue_t *queue)
{
{
        unsigned int nqueues;
        unsigned int nqueues;
        QE_t *q;
        QE_t *q;
 
 
        queue->alloc = queue->free = q = (QE_t *) kmalloc (SECTOR_SIZE, GFP_KERNEL);
        queue->alloc = queue->free = q = (QE_t *) kmalloc (SECTOR_SIZE, GFP_KERNEL);
        if (q) {
        if (q) {
                nqueues = SECTOR_SIZE / sizeof (QE_t);
                nqueues = SECTOR_SIZE / sizeof (QE_t);
 
 
                for (; nqueues; q++, nqueues--) {
                for (; nqueues; q++, nqueues--) {
                        q->next = q + 1;
                        q->next = q + 1;
                        q->prev = NULL;
                        q->prev = NULL;
                        q->magic = QUEUE_MAGIC_FREE;
                        q->magic = QUEUE_MAGIC_FREE;
                        q->SCpnt = NULL;
                        q->SCpnt = NULL;
                }
                }
                q -= 1;
                q -= 1;
                q->next = NULL;
                q->next = NULL;
        }
        }
 
 
        return q != NULL;
        return q != NULL;
}
}
 
 
/*
/*
 * Function: void queue_free (Queue_t *queue)
 * Function: void queue_free (Queue_t *queue)
 * Purpose : free a queue
 * Purpose : free a queue
 * Params  : queue - queue to free
 * Params  : queue - queue to free
 */
 */
void queue_free (Queue_t *queue)
void queue_free (Queue_t *queue)
{
{
        if (queue->alloc)
        if (queue->alloc)
                kfree (queue->alloc);
                kfree (queue->alloc);
}
}
 
 
 
 
/*
/*
 * Function: int queue_add_cmd_ordered (Queue_t *queue, Scsi_Cmnd *SCpnt)
 * Function: int queue_add_cmd_ordered (Queue_t *queue, Scsi_Cmnd *SCpnt)
 * Purpose : Add a new command onto a queue, adding REQUEST_SENSE to head.
 * Purpose : Add a new command onto a queue, adding REQUEST_SENSE to head.
 * Params  : queue - destination queue
 * Params  : queue - destination queue
 *           SCpnt - command to add
 *           SCpnt - command to add
 * Returns : 0 on error, !0 on success
 * Returns : 0 on error, !0 on success
 */
 */
int queue_add_cmd_ordered (Queue_t *queue, Scsi_Cmnd *SCpnt)
int queue_add_cmd_ordered (Queue_t *queue, Scsi_Cmnd *SCpnt)
{
{
        unsigned long flags;
        unsigned long flags;
        QE_t *q;
        QE_t *q;
 
 
        save_flags_cli (flags);
        save_flags_cli (flags);
        q = queue->free;
        q = queue->free;
        if (q)
        if (q)
                queue->free = q->next;
                queue->free = q->next;
 
 
        if (q) {
        if (q) {
                if (q->magic != QUEUE_MAGIC_FREE) {
                if (q->magic != QUEUE_MAGIC_FREE) {
                        restore_flags (flags);
                        restore_flags (flags);
                        panic ("scsi queues corrupted - queue entry %p not free", q);
                        panic ("scsi queues corrupted - queue entry %p not free", q);
                }
                }
 
 
                q->magic = QUEUE_MAGIC_USED;
                q->magic = QUEUE_MAGIC_USED;
                q->SCpnt = SCpnt;
                q->SCpnt = SCpnt;
 
 
                if (SCpnt->cmnd[0] == REQUEST_SENSE) { /* request_sense gets put on the queue head */
                if (SCpnt->cmnd[0] == REQUEST_SENSE) { /* request_sense gets put on the queue head */
                        if (queue->head) {
                        if (queue->head) {
                                q->prev = NULL;
                                q->prev = NULL;
                                q->next = queue->head;
                                q->next = queue->head;
                                queue->head->prev = q;
                                queue->head->prev = q;
                                queue->head = q;
                                queue->head = q;
                        } else {
                        } else {
                                q->next = q->prev = NULL;
                                q->next = q->prev = NULL;
                                queue->head = queue->tail = q;
                                queue->head = queue->tail = q;
                        }
                        }
                } else {                                /* others get put on the tail */
                } else {                                /* others get put on the tail */
                        if (queue->tail) {
                        if (queue->tail) {
                                q->next = NULL;
                                q->next = NULL;
                                q->prev = queue->tail;
                                q->prev = queue->tail;
                                queue->tail->next = q;
                                queue->tail->next = q;
                                queue->tail = q;
                                queue->tail = q;
                        } else {
                        } else {
                                q->next = q->prev = NULL;
                                q->next = q->prev = NULL;
                                queue->head = queue->tail = q;
                                queue->head = queue->tail = q;
                        }
                        }
                }
                }
        }
        }
        restore_flags (flags);
        restore_flags (flags);
 
 
        return q != NULL;
        return q != NULL;
}
}
 
 
/*
/*
 * Function: int queue_add_cmd_tail (Queue_t *queue, Scsi_Cmnd *SCpnt)
 * Function: int queue_add_cmd_tail (Queue_t *queue, Scsi_Cmnd *SCpnt)
 * Purpose : Add a new command onto a queue, adding onto tail of list
 * Purpose : Add a new command onto a queue, adding onto tail of list
 * Params  : queue - destination queue
 * Params  : queue - destination queue
 *           SCpnt - command to add
 *           SCpnt - command to add
 * Returns : 0 on error, !0 on success
 * Returns : 0 on error, !0 on success
 */
 */
int queue_add_cmd_tail (Queue_t *queue, Scsi_Cmnd *SCpnt)
int queue_add_cmd_tail (Queue_t *queue, Scsi_Cmnd *SCpnt)
{
{
        unsigned long flags;
        unsigned long flags;
        QE_t *q;
        QE_t *q;
 
 
        save_flags_cli (flags);
        save_flags_cli (flags);
        q = queue->free;
        q = queue->free;
        if (q)
        if (q)
                queue->free = q->next;
                queue->free = q->next;
 
 
        if (q) {
        if (q) {
                if (q->magic != QUEUE_MAGIC_FREE) {
                if (q->magic != QUEUE_MAGIC_FREE) {
                        restore_flags (flags);
                        restore_flags (flags);
                        panic ("scsi queues corrupted - queue entry %p not free", q);
                        panic ("scsi queues corrupted - queue entry %p not free", q);
                }
                }
 
 
                q->magic = QUEUE_MAGIC_USED;
                q->magic = QUEUE_MAGIC_USED;
                q->SCpnt = SCpnt;
                q->SCpnt = SCpnt;
 
 
                if (queue->tail) {
                if (queue->tail) {
                        q->next = NULL;
                        q->next = NULL;
                        q->prev = queue->tail;
                        q->prev = queue->tail;
                        queue->tail->next = q;
                        queue->tail->next = q;
                        queue->tail = q;
                        queue->tail = q;
                } else {
                } else {
                        q->next = q->prev = NULL;
                        q->next = q->prev = NULL;
                        queue->head = queue->tail = q;
                        queue->head = queue->tail = q;
                }
                }
        }
        }
        restore_flags (flags);
        restore_flags (flags);
 
 
        return q != NULL;
        return q != NULL;
}
}
 
 
/*
/*
 * Function: Scsi_Cmnd *queue_remove_exclude (queue, exclude)
 * Function: Scsi_Cmnd *queue_remove_exclude (queue, exclude)
 * Purpose : remove a SCSI command from a queue
 * Purpose : remove a SCSI command from a queue
 * Params  : queue   - queue to remove command from
 * Params  : queue   - queue to remove command from
 *           exclude - bit array of target&lun which is busy
 *           exclude - bit array of target&lun which is busy
 * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
 * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
 */
 */
Scsi_Cmnd *queue_remove_exclude (Queue_t *queue, unsigned char *exclude)
Scsi_Cmnd *queue_remove_exclude (Queue_t *queue, unsigned char *exclude)
{
{
        unsigned long flags;
        unsigned long flags;
        Scsi_Cmnd *SCpnt;
        Scsi_Cmnd *SCpnt;
        QE_t *q, *prev;
        QE_t *q, *prev;
 
 
        save_flags_cli (flags);
        save_flags_cli (flags);
        for (q = queue->head, prev = NULL; q; q = q->next) {
        for (q = queue->head, prev = NULL; q; q = q->next) {
                if (exclude && !test_bit (q->SCpnt->target * 8 + q->SCpnt->lun, exclude))
                if (exclude && !test_bit (q->SCpnt->target * 8 + q->SCpnt->lun, exclude))
                        break;
                        break;
                prev = q;
                prev = q;
        }
        }
 
 
        if (q) {
        if (q) {
                if (q->magic != QUEUE_MAGIC_USED) {
                if (q->magic != QUEUE_MAGIC_USED) {
                        restore_flags (flags);
                        restore_flags (flags);
                        panic ("q_remove_exclude: scsi queues corrupted - queue entry not used");
                        panic ("q_remove_exclude: scsi queues corrupted - queue entry not used");
                }
                }
                if (q->prev != prev)
                if (q->prev != prev)
                        panic ("q_remove_exclude: scsi queues corrupted - q->prev != prev");
                        panic ("q_remove_exclude: scsi queues corrupted - q->prev != prev");
 
 
                if (!prev) {
                if (!prev) {
                        queue->head = q->next;
                        queue->head = q->next;
                        if (queue->head)
                        if (queue->head)
                                queue->head->prev = NULL;
                                queue->head->prev = NULL;
                        else
                        else
                                queue->tail = NULL;
                                queue->tail = NULL;
                } else {
                } else {
                        prev->next = q->next;
                        prev->next = q->next;
                        if (prev->next)
                        if (prev->next)
                                prev->next->prev = prev;
                                prev->next->prev = prev;
                        else
                        else
                                queue->tail = prev;
                                queue->tail = prev;
                }
                }
 
 
                SCpnt = q->SCpnt;
                SCpnt = q->SCpnt;
 
 
                q->next = queue->free;
                q->next = queue->free;
                queue->free = q;
                queue->free = q;
                q->magic = QUEUE_MAGIC_FREE;
                q->magic = QUEUE_MAGIC_FREE;
        } else
        } else
                SCpnt = NULL;
                SCpnt = NULL;
 
 
        restore_flags (flags);
        restore_flags (flags);
 
 
        return SCpnt;
        return SCpnt;
}
}
 
 
/*
/*
 * Function: Scsi_Cmnd *queue_remove (queue)
 * Function: Scsi_Cmnd *queue_remove (queue)
 * Purpose : removes first SCSI command from a queue
 * Purpose : removes first SCSI command from a queue
 * Params  : queue   - queue to remove command from
 * Params  : queue   - queue to remove command from
 * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
 * Returns : Scsi_Cmnd if successful (and a reference), or NULL if no command available
 */
 */
Scsi_Cmnd *queue_remove (Queue_t *queue)
Scsi_Cmnd *queue_remove (Queue_t *queue)
{
{
        unsigned long flags;
        unsigned long flags;
        Scsi_Cmnd *SCpnt;
        Scsi_Cmnd *SCpnt;
        QE_t *q;
        QE_t *q;
 
 
        save_flags_cli (flags);
        save_flags_cli (flags);
        q = queue->head;
        q = queue->head;
        if (q) {
        if (q) {
                queue->head = q->next;
                queue->head = q->next;
                if (queue->head)
                if (queue->head)
                        queue->head->prev = NULL;
                        queue->head->prev = NULL;
                else
                else
                        queue->tail = NULL;
                        queue->tail = NULL;
 
 
                if (q->magic != QUEUE_MAGIC_USED) {
                if (q->magic != QUEUE_MAGIC_USED) {
                        restore_flags (flags);
                        restore_flags (flags);
                        panic ("scsi queues corrupted - queue entry not used");
                        panic ("scsi queues corrupted - queue entry not used");
                }
                }
 
 
                SCpnt = q->SCpnt;
                SCpnt = q->SCpnt;
 
 
                q->next = queue->free;
                q->next = queue->free;
                queue->free = q;
                queue->free = q;
                q->magic = QUEUE_MAGIC_FREE;
                q->magic = QUEUE_MAGIC_FREE;
        } else
        } else
                SCpnt = NULL;
                SCpnt = NULL;
 
 
        restore_flags (flags);
        restore_flags (flags);
 
 
        return SCpnt;
        return SCpnt;
}
}
 
 
/*
/*
 * Function: Scsi_Cmnd *queue_remove_tgtluntag (queue, target, lun, tag)
 * Function: Scsi_Cmnd *queue_remove_tgtluntag (queue, target, lun, tag)
 * Purpose : remove a SCSI command from the queue for a specified target/lun/tag
 * Purpose : remove a SCSI command from the queue for a specified target/lun/tag
 * Params  : queue  - queue to remove command from
 * Params  : queue  - queue to remove command from
 *           target - target that we want
 *           target - target that we want
 *           lun    - lun on device
 *           lun    - lun on device
 *           tag    - tag on device
 *           tag    - tag on device
 * Returns : Scsi_Cmnd if successful, or NULL if no command satisfies requirements
 * Returns : Scsi_Cmnd if successful, or NULL if no command satisfies requirements
 */
 */
Scsi_Cmnd *queue_remove_tgtluntag (Queue_t *queue, int target, int lun, int tag)
Scsi_Cmnd *queue_remove_tgtluntag (Queue_t *queue, int target, int lun, int tag)
{
{
        unsigned long flags;
        unsigned long flags;
        Scsi_Cmnd *SCpnt;
        Scsi_Cmnd *SCpnt;
        QE_t *q, *prev;
        QE_t *q, *prev;
 
 
        save_flags_cli (flags);
        save_flags_cli (flags);
        for (q = queue->head, prev = NULL; q; q = q->next) {
        for (q = queue->head, prev = NULL; q; q = q->next) {
                if (q->SCpnt->target == target &&
                if (q->SCpnt->target == target &&
                    q->SCpnt->lun == lun &&
                    q->SCpnt->lun == lun &&
                    q->SCpnt->tag == tag)
                    q->SCpnt->tag == tag)
                        break;
                        break;
 
 
                prev = q;
                prev = q;
        }
        }
 
 
        if (q) {
        if (q) {
                if (q->magic != QUEUE_MAGIC_USED) {
                if (q->magic != QUEUE_MAGIC_USED) {
                        restore_flags (flags);
                        restore_flags (flags);
                        panic ("q_remove_tgtluntag: scsi queues corrupted - queue entry not used");
                        panic ("q_remove_tgtluntag: scsi queues corrupted - queue entry not used");
                }
                }
                if (q->prev != prev)
                if (q->prev != prev)
                        panic ("q_remove_tgtluntag: scsi queues corrupted - q->prev != prev");
                        panic ("q_remove_tgtluntag: scsi queues corrupted - q->prev != prev");
 
 
                if (!prev) {
                if (!prev) {
                        queue->head = q->next;
                        queue->head = q->next;
                        if (queue->head)
                        if (queue->head)
                                queue->head->prev = NULL;
                                queue->head->prev = NULL;
                        else
                        else
                                queue->tail = NULL;
                                queue->tail = NULL;
                } else {
                } else {
                        prev->next = q->next;
                        prev->next = q->next;
                        if (prev->next)
                        if (prev->next)
                                prev->next->prev = prev;
                                prev->next->prev = prev;
                        else
                        else
                                queue->tail = prev;
                                queue->tail = prev;
                }
                }
 
 
                SCpnt = q->SCpnt;
                SCpnt = q->SCpnt;
 
 
                q->magic = QUEUE_MAGIC_FREE;
                q->magic = QUEUE_MAGIC_FREE;
                q->next = queue->free;
                q->next = queue->free;
                queue->free = q;
                queue->free = q;
        } else
        } else
                SCpnt = NULL;
                SCpnt = NULL;
 
 
        restore_flags (flags);
        restore_flags (flags);
 
 
        return SCpnt;
        return SCpnt;
}
}
 
 
/*
/*
 * Function: int queue_probetgtlun (queue, target, lun)
 * Function: int queue_probetgtlun (queue, target, lun)
 * Purpose : check to see if we have a command in the queue for the specified
 * Purpose : check to see if we have a command in the queue for the specified
 *           target/lun.
 *           target/lun.
 * Params  : queue  - queue to look in
 * Params  : queue  - queue to look in
 *           target - target we want to probe
 *           target - target we want to probe
 *           lun    - lun on target
 *           lun    - lun on target
 * Returns : 0 if not found, != 0 if found
 * Returns : 0 if not found, != 0 if found
 */
 */
int queue_probetgtlun (Queue_t *queue, int target, int lun)
int queue_probetgtlun (Queue_t *queue, int target, int lun)
{
{
        QE_t *q;
        QE_t *q;
 
 
        for (q = queue->head; q; q = q->next)
        for (q = queue->head; q; q = q->next)
                if (q->SCpnt->target == target &&
                if (q->SCpnt->target == target &&
                    q->SCpnt->lun == lun)
                    q->SCpnt->lun == lun)
                        break;
                        break;
 
 
        return q != NULL;
        return q != NULL;
}
}
 
 
/*
/*
 * Function: int queue_cmdonqueue (queue, SCpnt)
 * Function: int queue_cmdonqueue (queue, SCpnt)
 * Purpose : check to see if we have a command on the queue
 * Purpose : check to see if we have a command on the queue
 * Params  : queue - queue to look in
 * Params  : queue - queue to look in
 *           SCpnt - command to find
 *           SCpnt - command to find
 * Returns : 0 if not found, != 0 if found
 * Returns : 0 if not found, != 0 if found
 */
 */
int queue_cmdonqueue (Queue_t *queue, Scsi_Cmnd *SCpnt)
int queue_cmdonqueue (Queue_t *queue, Scsi_Cmnd *SCpnt)
{
{
        QE_t *q;
        QE_t *q;
 
 
        for (q = queue->head; q; q = q->next)
        for (q = queue->head; q; q = q->next)
                if (q->SCpnt == SCpnt)
                if (q->SCpnt == SCpnt)
                        break;
                        break;
 
 
        return q != NULL;
        return q != NULL;
}
}
 
 
/*
/*
 * Function: int queue_removecmd (Queue_t *queue, Scsi_Cmnd *SCpnt)
 * Function: int queue_removecmd (Queue_t *queue, Scsi_Cmnd *SCpnt)
 * Purpose : remove a specific command from the queues
 * Purpose : remove a specific command from the queues
 * Params  : queue - queue to look in
 * Params  : queue - queue to look in
 *           SCpnt - command to find
 *           SCpnt - command to find
 * Returns : 0 if not found
 * Returns : 0 if not found
 */
 */
int queue_removecmd (Queue_t *queue, Scsi_Cmnd *SCpnt)
int queue_removecmd (Queue_t *queue, Scsi_Cmnd *SCpnt)
{
{
        unsigned long flags;
        unsigned long flags;
        QE_t *q, *prev;
        QE_t *q, *prev;
 
 
        save_flags_cli (flags);
        save_flags_cli (flags);
        for (q = queue->head, prev = NULL; q; q = q->next) {
        for (q = queue->head, prev = NULL; q; q = q->next) {
                if (q->SCpnt == SCpnt)
                if (q->SCpnt == SCpnt)
                        break;
                        break;
 
 
                prev = q;
                prev = q;
        }
        }
 
 
        if (q) {
        if (q) {
                if (q->magic != QUEUE_MAGIC_USED) {
                if (q->magic != QUEUE_MAGIC_USED) {
                        restore_flags (flags);
                        restore_flags (flags);
                        panic ("q_removecmd: scsi queues corrupted - queue entry not used");
                        panic ("q_removecmd: scsi queues corrupted - queue entry not used");
                }
                }
                if (q->prev != prev)
                if (q->prev != prev)
                        panic ("q_removecmd: scsi queues corrupted - q->prev != prev");
                        panic ("q_removecmd: scsi queues corrupted - q->prev != prev");
 
 
                if (!prev) {
                if (!prev) {
                        queue->head = q->next;
                        queue->head = q->next;
                        if (queue->head)
                        if (queue->head)
                                queue->head->prev = NULL;
                                queue->head->prev = NULL;
                        else
                        else
                                queue->tail = NULL;
                                queue->tail = NULL;
                } else {
                } else {
                        prev->next = q->next;
                        prev->next = q->next;
                        if (prev->next)
                        if (prev->next)
                                prev->next->prev = prev;
                                prev->next->prev = prev;
                        else
                        else
                                queue->tail = prev;
                                queue->tail = prev;
                }
                }
 
 
                q->magic = QUEUE_MAGIC_FREE;
                q->magic = QUEUE_MAGIC_FREE;
                q->next = queue->free;
                q->next = queue->free;
                queue->free = q;
                queue->free = q;
        }
        }
 
 
        restore_flags (flags);
        restore_flags (flags);
 
 
        return q != NULL;
        return q != NULL;
}
}
 
 

powered by: WebSVN 2.1.0

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