patch-2.3.41 linux/drivers/scsi/scsi.c
Next file: linux/drivers/scsi/scsi.h
Previous file: linux/drivers/scsi/qlogicpti.c
Back to the patch index
Back to the overall index
- Lines: 1446
- Date:
Tue Jan 25 10:41:46 2000
- Orig file:
v2.3.40/linux/drivers/scsi/scsi.c
- Orig date:
Fri Jan 21 18:19:16 2000
diff -u --recursive --new-file v2.3.40/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
@@ -86,44 +86,11 @@
* Definitions and constants.
*/
-/*
- * PAGE_SIZE must be a multiple of the sector size (512). True
- * for all reasonably recent architectures (even the VAX...).
- */
-#define SECTOR_SIZE 512
-#define SECTORS_PER_PAGE (PAGE_SIZE/SECTOR_SIZE)
-
-#if SECTORS_PER_PAGE <= 8
-typedef unsigned char FreeSectorBitmap;
-#elif SECTORS_PER_PAGE <= 32
-typedef unsigned int FreeSectorBitmap;
-#else
-#error You lose.
-#endif
-
#define MIN_RESET_DELAY (2*HZ)
/* Do not call reset on error if we just did a reset within 15 sec. */
#define MIN_RESET_PERIOD (15*HZ)
-/* The following devices are known not to tolerate a lun != 0 scan for
- * one reason or another. Some will respond to all luns, others will
- * lock up.
- */
-
-#define BLIST_NOLUN 0x001
-#define BLIST_FORCELUN 0x002
-#define BLIST_BORKEN 0x004
-#define BLIST_KEY 0x008
-#define BLIST_SINGLELUN 0x010
-#define BLIST_NOTQ 0x020
-#define BLIST_SPARSELUN 0x040
-#define BLIST_MAX5LUN 0x080
-#define BLIST_ISDISK 0x100
-#define BLIST_ISROM 0x200
-#define BLIST_GHOST 0x400
-
-
/*
* Data declarations.
@@ -139,12 +106,6 @@
static unsigned long serial_number = 0;
static Scsi_Cmnd *scsi_bh_queue_head = NULL;
static Scsi_Cmnd *scsi_bh_queue_tail = NULL;
-static FreeSectorBitmap *dma_malloc_freelist = NULL;
-static int need_isa_bounce_buffers;
-static unsigned int dma_sectors = 0;
-unsigned int scsi_dma_free_sectors = 0;
-unsigned int scsi_need_isa_buffer = 0;
-static unsigned char **dma_malloc_pages = NULL;
/*
* Note - the initial logging level can be set here to log events at boot time.
@@ -173,12 +134,7 @@
/*
* Function prototypes.
*/
-static void resize_dma_pool(void);
-static void print_inquiry(unsigned char *data);
extern void scsi_times_out(Scsi_Cmnd * SCpnt);
-static int scan_scsis_single(int channel, int dev, int lun, int *max_scsi_dev,
- int *sparse_lun, Scsi_Device ** SDpnt, Scsi_Cmnd * SCpnt,
- struct Scsi_Host *shpnt, char *scsi_result);
void scsi_build_commandblocks(Scsi_Device * SDpnt);
static int scsi_unregister_device(struct Scsi_Device_Template *tpnt);
@@ -189,140 +145,40 @@
extern void scsi_old_done(Scsi_Cmnd * SCpnt);
extern void scsi_old_times_out(Scsi_Cmnd * SCpnt);
-struct dev_info {
- const char *vendor;
- const char *model;
- const char *revision; /* Latest revision known to be bad. Not used yet */
- unsigned flags;
-};
/*
- * This is what was previously known as the blacklist. The concept
- * has been expanded so that we can specify other types of things we
- * need to be aware of.
- */
-static struct dev_info device_list[] =
-{
- {"Aashima", "IMAGERY 2400SP", "1.03", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
- {"CHINON", "CD-ROM CDS-431", "H42", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
- {"CHINON", "CD-ROM CDS-535", "Q14", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
- {"DENON", "DRD-25X", "V", BLIST_NOLUN}, /* Locks up if probed for lun != 0 */
- {"HITACHI", "DK312C", "CM81", BLIST_NOLUN}, /* Responds to all lun - dtg */
- {"HITACHI", "DK314C", "CR21", BLIST_NOLUN}, /* responds to all lun */
- {"IMS", "CDD521/10", "2.06", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */
- {"MAXTOR", "XT-3280", "PR02", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */
- {"MAXTOR", "XT-4380S", "B3C", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */
- {"MAXTOR", "MXT-1240S", "I1.2", BLIST_NOLUN}, /* Locks up when LUN>0 polled */
- {"MAXTOR", "XT-4170S", "B5A", BLIST_NOLUN}, /* Locks-up sometimes when LUN>0 polled. */
- {"MAXTOR", "XT-8760S", "B7B", BLIST_NOLUN}, /* guess what? */
- {"MEDIAVIS", "RENO CD-ROMX2A", "2.03", BLIST_NOLUN}, /*Responds to all lun */
- {"MICROP", "4110", "*", BLIST_NOTQ}, /* Buggy Tagged Queuing */
- {"NEC", "CD-ROM DRIVE:841", "1.0", BLIST_NOLUN}, /* Locks-up when LUN>0 polled. */
- {"PHILIPS", "PCA80SC", "V4-2", BLIST_NOLUN}, /* Responds to all lun */
- {"RODIME", "RO3000S", "2.33", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
- {"SANYO", "CRD-250S", "1.20", BLIST_NOLUN}, /* causes failed REQUEST SENSE on lun 1
- * for aha152x controller, which causes
- * SCSI code to reset bus.*/
- {"SEAGATE", "ST157N", "\004|j", BLIST_NOLUN}, /* causes failed REQUEST SENSE on lun 1
- * for aha152x controller, which causes
- * SCSI code to reset bus.*/
- {"SEAGATE", "ST296", "921", BLIST_NOLUN}, /* Responds to all lun */
- {"SEAGATE", "ST1581", "6538", BLIST_NOLUN}, /* Responds to all lun */
- {"SONY", "CD-ROM CDU-541", "4.3d", BLIST_NOLUN},
- {"SONY", "CD-ROM CDU-55S", "1.0i", BLIST_NOLUN},
- {"SONY", "CD-ROM CDU-561", "1.7x", BLIST_NOLUN},
- {"SONY", "CD-ROM CDU-8012", "*", BLIST_NOLUN},
- {"TANDBERG", "TDC 3600", "U07", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
- {"TEAC", "CD-R55S", "1.0H", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
- {"TEAC", "CD-ROM", "1.06", BLIST_NOLUN}, /* causes failed REQUEST SENSE on lun 1
- * for seagate controller, which causes
- * SCSI code to reset bus.*/
- {"TEAC", "MT-2ST/45S2-27", "RV M", BLIST_NOLUN}, /* Responds to all lun */
- {"TEXEL", "CD-ROM", "1.06", BLIST_NOLUN}, /* causes failed REQUEST SENSE on lun 1
- * for seagate controller, which causes
- * SCSI code to reset bus.*/
- {"QUANTUM", "LPS525S", "3110", BLIST_NOLUN}, /* Locks sometimes if polled for lun != 0 */
- {"QUANTUM", "PD1225S", "3110", BLIST_NOLUN}, /* Locks sometimes if polled for lun != 0 */
- {"QUANTUM", "FIREBALL ST4.3S", "0F0C", BLIST_NOLUN}, /* Locks up when polled for lun != 0 */
- {"MEDIAVIS", "CDR-H93MV", "1.31", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
- {"SANKYO", "CP525", "6.64", BLIST_NOLUN}, /* causes failed REQ SENSE, extra reset */
- {"HP", "C1750A", "3226", BLIST_NOLUN}, /* scanjet iic */
- {"HP", "C1790A", "", BLIST_NOLUN}, /* scanjet iip */
- {"HP", "C2500A", "", BLIST_NOLUN}, /* scanjet iicx */
- {"YAMAHA", "CDR100", "1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0 */
- {"YAMAHA", "CDR102", "1.00", BLIST_NOLUN}, /* Locks up if polled for lun != 0
- * extra reset */
- {"RELISYS", "Scorpio", "*", BLIST_NOLUN}, /* responds to all LUN */
- {"MICROTEK", "ScanMaker II", "5.61", BLIST_NOLUN}, /* responds to all LUN */
-
-/*
- * Other types of devices that have special flags.
- */
- {"SONY", "CD-ROM CDU-8001", "*", BLIST_BORKEN},
- {"TEXEL", "CD-ROM", "1.06", BLIST_BORKEN},
- {"IOMEGA", "Io20S *F", "*", BLIST_KEY},
- {"INSITE", "Floptical F*8I", "*", BLIST_KEY},
- {"INSITE", "I325VM", "*", BLIST_KEY},
- {"NRC", "MBR-7", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
- {"NRC", "MBR-7.4", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
- {"REGAL", "CDC-4X", "*", BLIST_MAX5LUN | BLIST_SINGLELUN},
- {"NAKAMICH", "MJ-4.8S", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
- {"NAKAMICH", "MJ-5.16S", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
- {"PIONEER", "CD-ROM DRM-600", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
- {"PIONEER", "CD-ROM DRM-602X", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
- {"PIONEER", "CD-ROM DRM-604X", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
- {"EMULEX", "MD21/S2 ESDI", "*", BLIST_SINGLELUN},
- {"CANON", "IPUBJD", "*", BLIST_SPARSELUN},
- {"nCipher", "Fastness Crypto", "*", BLIST_FORCELUN},
- {"NEC", "PD-1 ODX654P", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
- {"MATSHITA", "PD-1", "*", BLIST_FORCELUN | BLIST_SINGLELUN},
- {"iomega", "jaz 1GB", "J.86", BLIST_NOTQ | BLIST_NOLUN},
- {"CREATIVE","DVD-RAM RAM","*", BLIST_GHOST},
- {"MATSHITA","PD-2 LF-D100","*", BLIST_GHOST},
- {"HITACHI", "GF-1050","*", BLIST_GHOST}, /* Hitachi SCSI DVD-RAM */
- {"TOSHIBA","CDROM","*", BLIST_ISROM},
- {"TOSHIBA","DVD-RAM SD-W1101","*", BLIST_GHOST},
- {"TOSHIBA","DVD-RAM SD-W1111","*", BLIST_GHOST},
-
- /*
- * Must be at end of list...
- */
- {NULL, NULL, NULL}
-};
-
-static int get_device_flags(unsigned char *response_data)
-{
- int i = 0;
- unsigned char *pnt;
- for (i = 0; 1; i++) {
- if (device_list[i].vendor == NULL)
- return 0;
- pnt = &response_data[8];
- while (*pnt && *pnt == ' ')
- pnt++;
- if (memcmp(device_list[i].vendor, pnt,
- strlen(device_list[i].vendor)))
- continue;
- pnt = &response_data[16];
- while (*pnt && *pnt == ' ')
- pnt++;
- if (memcmp(device_list[i].model, pnt,
- strlen(device_list[i].model)))
- continue;
- return device_list[i].flags;
- }
- return 0;
-}
-
-
-static void scan_scsis_done(Scsi_Cmnd * SCpnt)
-{
-
- SCSI_LOG_MLCOMPLETE(1, printk("scan_scsis_done(%p, %06x)\n", SCpnt->host, SCpnt->result));
- SCpnt->request.rq_status = RQ_SCSI_DONE;
-
- if (SCpnt->request.sem != NULL)
- up(SCpnt->request.sem);
+ * Function: scsi_get_request_handler()
+ *
+ * Purpose: Selects queue handler function for a device.
+ *
+ * Arguments: SDpnt - device for which we need a handler function.
+ *
+ * Returns: Nothing
+ *
+ * Lock status: No locking assumed or required.
+ *
+ * Notes: Most devices will end up using scsi_request_fn for the
+ * handler function (at least as things are done now).
+ * The "block" feature basically ensures that only one of
+ * the blocked hosts is active at one time, mainly to work around
+ * buggy DMA chipsets where the memory gets starved.
+ * For this case, we have a special handler function, which
+ * does some checks and ultimately calls scsi_request_fn.
+ *
+ * As a future enhancement, it might be worthwhile to add support
+ * for stacked handlers - there might get to be too many permutations
+ * otherwise. Then again, we might just have one handler that does
+ * all of the special cases (a little bit slower), and those devices
+ * that don't need the special case code would directly call
+ * scsi_request_fn.
+ *
+ * As it stands, I can think of a number of special cases that
+ * we might need to handle. This would not only include the blocked
+ * case, but single_lun (for changers), and any special handling
+ * we might need for a spun-down disk to spin it back up again.
+ */
+request_fn_proc * scsi_get_request_handler(Scsi_Device * SDpnt, struct Scsi_Host * SHpnt) {
+ return scsi_request_fn;
}
#ifdef MODULE
@@ -349,43 +205,24 @@
#endif
-#ifdef CONFIG_SCSI_MULTI_LUN
-static int max_scsi_luns = 8;
-#else
-static int max_scsi_luns = 1;
-#endif
-
-#ifdef MODULE
-
-MODULE_PARM(max_scsi_luns, "i");
-MODULE_PARM_DESC(max_scsi_luns, "last scsi LUN (should be between 1 and 8)");
-
-#else
-
-static int __init scsi_luns_setup(char *str)
+/*
+ * Issue a command and wait for it to complete
+ */
+
+static void scsi_wait_done(Scsi_Cmnd * SCpnt)
{
- int tmp;
+ struct request *req;
- if (get_option(&str, &tmp) == 1) {
- max_scsi_luns = tmp;
- return 1;
- } else {
- printk("scsi_luns_setup : usage max_scsi_luns=n "
- "(n should be between 1 and 8)\n");
- return 0;
+ req = &SCpnt->request;
+ req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */
+
+ if (req->sem != NULL) {
+ up(req->sem);
}
}
-__setup("max_scsi_luns=", scsi_luns_setup);
-
-#endif
-
-/*
- * Issue a command and wait for it to complete
- */
-
void scsi_wait_cmd (Scsi_Cmnd * SCpnt, const void *cmnd ,
- void *buffer, unsigned bufflen, void (*done)(Scsi_Cmnd *),
+ void *buffer, unsigned bufflen,
int timeout, int retries)
{
DECLARE_MUTEX_LOCKED(sem);
@@ -393,595 +230,13 @@
SCpnt->request.sem = &sem;
SCpnt->request.rq_status = RQ_SCSI_BUSY;
scsi_do_cmd (SCpnt, (void *) cmnd,
- buffer, bufflen, done, timeout, retries);
+ buffer, bufflen, scsi_wait_done, timeout, retries);
down (&sem);
SCpnt->request.sem = NULL;
}
/*
- * Detecting SCSI devices :
- * We scan all present host adapter's busses, from ID 0 to ID (max_id).
- * We use the INQUIRY command, determine device type, and pass the ID /
- * lun address of all sequential devices to the tape driver, all random
- * devices to the disk driver.
- */
-static void scan_scsis(struct Scsi_Host *shpnt,
- unchar hardcoded,
- unchar hchannel,
- unchar hid,
- unchar hlun)
-{
- int channel;
- int dev;
- int lun;
- int max_dev_lun;
- Scsi_Cmnd *SCpnt;
- unsigned char *scsi_result;
- unsigned char scsi_result0[256];
- Scsi_Device *SDpnt;
- Scsi_Device *SDtail;
- int sparse_lun;
-
- scsi_result = NULL;
- SCpnt = (Scsi_Cmnd *) scsi_init_malloc(sizeof(Scsi_Cmnd),
- GFP_ATOMIC | GFP_DMA);
- if (SCpnt) {
- SDpnt = (Scsi_Device *) scsi_init_malloc(sizeof(Scsi_Device),
- GFP_ATOMIC);
- if (SDpnt) {
- /*
- * Register the queue for the device. All I/O requests will come
- * in through here. We also need to register a pointer to
- * ourselves, since the queue handler won't know what device
- * the queue actually represents. We could look it up, but it
- * is pointless work.
- */
- blk_init_queue(&SDpnt->request_queue, scsi_request_fn);
- blk_queue_headactive(&SDpnt->request_queue, 0);
- SDpnt->request_queue.queuedata = (void *) SDpnt;
- /* Make sure we have something that is valid for DMA purposes */
- scsi_result = ((!shpnt->unchecked_isa_dma)
- ? &scsi_result0[0] : scsi_init_malloc(512, GFP_DMA));
- }
- }
- if (scsi_result == NULL) {
- printk("Unable to obtain scsi_result buffer\n");
- goto leave;
- }
- /*
- * We must chain ourself in the host_queue, so commands can time out
- */
- SCpnt->next = NULL;
- SDpnt->device_queue = SCpnt;
- SDpnt->host = shpnt;
- SDpnt->online = TRUE;
-
- initialize_merge_fn(SDpnt);
-
- /*
- * Initialize the object that we will use to wait for command blocks.
- */
- init_waitqueue_head(&SDpnt->scpnt_wait);
-
- /*
- * Next, hook the device to the host in question.
- */
- SDpnt->prev = NULL;
- SDpnt->next = NULL;
- if (shpnt->host_queue != NULL) {
- SDtail = shpnt->host_queue;
- while (SDtail->next != NULL)
- SDtail = SDtail->next;
-
- SDtail->next = SDpnt;
- SDpnt->prev = SDtail;
- } else {
- shpnt->host_queue = SDpnt;
- }
-
- /*
- * We need to increment the counter for this one device so we can track when
- * things are quiet.
- */
- atomic_inc(&shpnt->host_active);
- atomic_inc(&SDpnt->device_active);
-
- if (hardcoded == 1) {
- Scsi_Device *oldSDpnt = SDpnt;
- struct Scsi_Device_Template *sdtpnt;
- channel = hchannel;
- if (channel > shpnt->max_channel)
- goto leave;
- dev = hid;
- if (dev >= shpnt->max_id)
- goto leave;
- lun = hlun;
- if (lun >= shpnt->max_lun)
- goto leave;
- scan_scsis_single(channel, dev, lun, &max_dev_lun, &sparse_lun,
- &SDpnt, SCpnt, shpnt, scsi_result);
- if (SDpnt != oldSDpnt) {
-
- /* it could happen the blockdevice hasn't yet been inited */
- for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
- if (sdtpnt->init && sdtpnt->dev_noticed)
- (*sdtpnt->init) ();
-
- for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
- if (sdtpnt->attach) {
- (*sdtpnt->attach) (oldSDpnt);
- if (oldSDpnt->attached) {
- scsi_build_commandblocks(oldSDpnt);
- if (0 == oldSDpnt->has_cmdblocks) {
- printk("scan_scsis: DANGER, no command blocks\n");
- /* What to do now ?? */
- }
- }
- }
- }
- resize_dma_pool();
-
- for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
- if (sdtpnt->finish && sdtpnt->nr_dev) {
- (*sdtpnt->finish) ();
- }
- }
- }
- } else {
- /* Actual LUN. PC ordering is 0->n IBM/spec ordering is n->0 */
- int order_dev;
-
- for (channel = 0; channel <= shpnt->max_channel; channel++) {
- for (dev = 0; dev < shpnt->max_id; ++dev) {
- if (shpnt->reverse_ordering)
- /* Shift to scanning 15,14,13... or 7,6,5,4, */
- order_dev = shpnt->max_id - dev - 1;
- else
- order_dev = dev;
-
- if (shpnt->this_id != order_dev) {
-
- /*
- * We need the for so our continue, etc. work fine. We put this in
- * a variable so that we can override it during the scan if we
- * detect a device *KNOWN* to have multiple logical units.
- */
- max_dev_lun = (max_scsi_luns < shpnt->max_lun ?
- max_scsi_luns : shpnt->max_lun);
- sparse_lun = 0;
- for (lun = 0; lun < max_dev_lun; ++lun) {
- if (!scan_scsis_single(channel, order_dev, lun, &max_dev_lun,
- &sparse_lun, &SDpnt, SCpnt, shpnt,
- scsi_result)
- && !sparse_lun)
- break; /* break means don't probe further for luns!=0 */
- } /* for lun ends */
- } /* if this_id != id ends */
- } /* for dev ends */
- } /* for channel ends */
- } /* if/else hardcoded */
-
- /*
- * We need to decrement the counter for this one device
- * so we know when everything is quiet.
- */
- atomic_dec(&shpnt->host_active);
- atomic_dec(&SDpnt->device_active);
-
- leave:
-
- { /* Unchain SCpnt from host_queue */
- Scsi_Device *prev, *next;
- Scsi_Device *dqptr;
-
- for (dqptr = shpnt->host_queue; dqptr != SDpnt; dqptr = dqptr->next)
- continue;
- if (dqptr) {
- prev = dqptr->prev;
- next = dqptr->next;
- if (prev)
- prev->next = next;
- else
- shpnt->host_queue = next;
- if (next)
- next->prev = prev;
- }
- }
-
- /* Last device block does not exist. Free memory. */
- if (SDpnt != NULL)
- scsi_init_free((char *) SDpnt, sizeof(Scsi_Device));
-
- if (SCpnt != NULL)
- scsi_init_free((char *) SCpnt, sizeof(Scsi_Cmnd));
-
- /* If we allocated a buffer so we could do DMA, free it now */
- if (scsi_result != &scsi_result0[0] && scsi_result != NULL) {
- scsi_init_free(scsi_result, 512);
- } {
- Scsi_Device *sdev;
- Scsi_Cmnd *scmd;
-
- SCSI_LOG_SCAN_BUS(4, printk("Host status for host %p:\n", shpnt));
- for (sdev = shpnt->host_queue; sdev; sdev = sdev->next) {
- SCSI_LOG_SCAN_BUS(4, printk("Device %d %p: ", sdev->id, sdev));
- for (scmd = sdev->device_queue; scmd; scmd = scmd->next) {
- SCSI_LOG_SCAN_BUS(4, printk("%p ", scmd));
- }
- SCSI_LOG_SCAN_BUS(4, printk("\n"));
- }
- }
-}
-
-/*
- * The worker for scan_scsis.
- * Returning 0 means Please don't ask further for lun!=0, 1 means OK go on.
- * Global variables used : scsi_devices(linked list)
- */
-int scan_scsis_single(int channel, int dev, int lun, int *max_dev_lun,
- int *sparse_lun, Scsi_Device ** SDpnt2, Scsi_Cmnd * SCpnt,
- struct Scsi_Host *shpnt, char *scsi_result)
-{
- unsigned char scsi_cmd[12];
- struct Scsi_Device_Template *sdtpnt;
- Scsi_Device *SDtail, *SDpnt = *SDpnt2;
- int bflags, type = -1;
- static int ghost_channel=-1, ghost_dev=-1;
- int org_lun = lun;
-
- SDpnt->host = shpnt;
- SDpnt->id = dev;
- SDpnt->lun = lun;
- SDpnt->channel = channel;
- SDpnt->online = TRUE;
-
-
- if ((channel == ghost_channel) && (dev == ghost_dev) && (lun == 1)) {
- SDpnt->lun = 0;
- } else {
- ghost_channel = ghost_dev = -1;
- }
-
-
- /* Some low level driver could use device->type (DB) */
- SDpnt->type = -1;
-
- /*
- * Assume that the device will have handshaking problems, and then fix this
- * field later if it turns out it doesn't
- */
- SDpnt->borken = 1;
- SDpnt->was_reset = 0;
- SDpnt->expecting_cc_ua = 0;
- SDpnt->starved = 0;
-
- scsi_cmd[0] = TEST_UNIT_READY;
- scsi_cmd[1] = lun << 5;
- scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[4] = scsi_cmd[5] = 0;
-
- SCpnt->host = SDpnt->host;
- SCpnt->device = SDpnt;
- SCpnt->target = SDpnt->id;
- SCpnt->lun = SDpnt->lun;
- SCpnt->channel = SDpnt->channel;
-
- scsi_wait_cmd (SCpnt, (void *) scsi_cmd,
- (void *) NULL,
- 0, scan_scsis_done, SCSI_TIMEOUT + 4 * HZ, 5);
-
- SCSI_LOG_SCAN_BUS(3, printk("scsi: scan_scsis_single id %d lun %d. Return code 0x%08x\n",
- dev, lun, SCpnt->result));
- SCSI_LOG_SCAN_BUS(3, print_driverbyte(SCpnt->result));
- SCSI_LOG_SCAN_BUS(3, print_hostbyte(SCpnt->result));
- SCSI_LOG_SCAN_BUS(3, printk("\n"));
-
- if (SCpnt->result) {
- if (((driver_byte(SCpnt->result) & DRIVER_SENSE) ||
- (status_byte(SCpnt->result) & CHECK_CONDITION)) &&
- ((SCpnt->sense_buffer[0] & 0x70) >> 4) == 7) {
- if (((SCpnt->sense_buffer[2] & 0xf) != NOT_READY) &&
- ((SCpnt->sense_buffer[2] & 0xf) != UNIT_ATTENTION) &&
- ((SCpnt->sense_buffer[2] & 0xf) != ILLEGAL_REQUEST || lun > 0))
- return 1;
- } else
- return 0;
- }
- SCSI_LOG_SCAN_BUS(3, printk("scsi: performing INQUIRY\n"));
- /*
- * Build an INQUIRY command block.
- */
- scsi_cmd[0] = INQUIRY;
- scsi_cmd[1] = (lun << 5) & 0xe0;
- scsi_cmd[2] = 0;
- scsi_cmd[3] = 0;
- scsi_cmd[4] = 255;
- scsi_cmd[5] = 0;
- SCpnt->cmd_len = 0;
-
- scsi_wait_cmd (SCpnt, (void *) scsi_cmd,
- (void *) scsi_result,
- 256, scan_scsis_done, SCSI_TIMEOUT, 3);
-
- SCSI_LOG_SCAN_BUS(3, printk("scsi: INQUIRY %s with code 0x%x\n",
- SCpnt->result ? "failed" : "successful", SCpnt->result));
-
- if (SCpnt->result)
- return 0; /* assume no peripheral if any sort of error */
-
- /*
- * Check the peripheral qualifier field - this tells us whether LUNS
- * are supported here or not.
- */
- if ((scsi_result[0] >> 5) == 3) {
- return 0; /* assume no peripheral if any sort of error */
- }
-
- /*
- * Get any flags for this device.
- */
- bflags = get_device_flags (scsi_result);
-
-
- /* The Toshiba ROM was "gender-changed" here as an inline hack.
- This is now much more generic.
- This is a mess: What we really want is to leave the scsi_result
- alone, and just change the SDpnt structure. And the SDpnt is what
- we want print_inquiry to print. -- REW
- */
- if (bflags & BLIST_ISDISK) {
- scsi_result[0] = TYPE_DISK;
- scsi_result[1] |= 0x80; /* removable */
- }
-
- if (bflags & BLIST_ISROM) {
- scsi_result[0] = TYPE_ROM;
- scsi_result[1] |= 0x80; /* removable */
- }
-
- if (bflags & BLIST_GHOST) {
- if ((ghost_channel == channel) && (ghost_dev == dev) && (org_lun == 1)) {
- lun=1;
- } else {
- ghost_channel = channel;
- ghost_dev = dev;
- scsi_result[0] = TYPE_MOD;
- scsi_result[1] |= 0x80; /* removable */
- }
- }
-
-
- memcpy(SDpnt->vendor, scsi_result + 8, 8);
- memcpy(SDpnt->model, scsi_result + 16, 16);
- memcpy(SDpnt->rev, scsi_result + 32, 4);
-
- SDpnt->removable = (0x80 & scsi_result[1]) >> 7;
- SDpnt->online = TRUE;
- SDpnt->lockable = SDpnt->removable;
- SDpnt->changed = 0;
- SDpnt->access_count = 0;
- SDpnt->busy = 0;
- SDpnt->has_cmdblocks = 0;
- /*
- * Currently, all sequential devices are assumed to be tapes, all random
- * devices disk, with the appropriate read only flags set for ROM / WORM
- * treated as RO.
- */
- switch (type = (scsi_result[0] & 0x1f)) {
- case TYPE_TAPE:
- case TYPE_DISK:
- case TYPE_MOD:
- case TYPE_PROCESSOR:
- case TYPE_SCANNER:
- case TYPE_MEDIUM_CHANGER:
- case TYPE_ENCLOSURE:
- SDpnt->writeable = 1;
- break;
- case TYPE_WORM:
- case TYPE_ROM:
- SDpnt->writeable = 0;
- break;
- default:
- printk("scsi: unknown type %d\n", type);
- }
-
- SDpnt->device_blocked = FALSE;
- SDpnt->device_busy = 0;
- SDpnt->single_lun = 0;
- SDpnt->soft_reset =
- (scsi_result[7] & 1) && ((scsi_result[3] & 7) == 2);
- SDpnt->random = (type == TYPE_TAPE) ? 0 : 1;
- SDpnt->type = (type & 0x1f);
-
- print_inquiry(scsi_result);
-
- for (sdtpnt = scsi_devicelist; sdtpnt;
- sdtpnt = sdtpnt->next)
- if (sdtpnt->detect)
- SDpnt->attached +=
- (*sdtpnt->detect) (SDpnt);
-
- SDpnt->scsi_level = scsi_result[2] & 0x07;
- if (SDpnt->scsi_level >= 2 ||
- (SDpnt->scsi_level == 1 &&
- (scsi_result[3] & 0x0f) == 1))
- SDpnt->scsi_level++;
-
- /*
- * Accommodate drivers that want to sleep when they should be in a polling
- * loop.
- */
- SDpnt->disconnect = 0;
-
-
- /*
- * Set the tagged_queue flag for SCSI-II devices that purport to support
- * tagged queuing in the INQUIRY data.
- */
- SDpnt->tagged_queue = 0;
- if ((SDpnt->scsi_level >= SCSI_2) &&
- (scsi_result[7] & 2) &&
- !(bflags & BLIST_NOTQ)) {
- SDpnt->tagged_supported = 1;
- SDpnt->current_tag = 0;
- }
- /*
- * Some revisions of the Texel CD ROM drives have handshaking problems when
- * used with the Seagate controllers. Before we know what type of device
- * we're talking to, we assume it's borken and then change it here if it
- * turns out that it isn't a TEXEL drive.
- */
- if ((bflags & BLIST_BORKEN) == 0)
- SDpnt->borken = 0;
-
- /*
- * If we want to only allow I/O to one of the luns attached to this device
- * at a time, then we set this flag.
- */
- if (bflags & BLIST_SINGLELUN)
- SDpnt->single_lun = 1;
-
- /*
- * These devices need this "key" to unlock the devices so we can use it
- */
- if ((bflags & BLIST_KEY) != 0) {
- printk("Unlocked floptical drive.\n");
- SDpnt->lockable = 0;
- scsi_cmd[0] = MODE_SENSE;
- scsi_cmd[1] = (lun << 5) & 0xe0;
- scsi_cmd[2] = 0x2e;
- scsi_cmd[3] = 0;
- scsi_cmd[4] = 0x2a;
- scsi_cmd[5] = 0;
- SCpnt->cmd_len = 0;
- scsi_wait_cmd (SCpnt, (void *) scsi_cmd,
- (void *) scsi_result, 0x2a,
- scan_scsis_done, SCSI_TIMEOUT, 3);
- }
- /*
- * Detach the command from the device. It was just a temporary to be used while
- * scanning the bus - the real ones will be allocated later.
- */
- SDpnt->device_queue = NULL;
-
- /*
- * This device was already hooked up to the host in question,
- * so at this point we just let go of it and it should be fine. We do need to
- * allocate a new one and attach it to the host so that we can further scan the bus.
- */
- SDpnt = (Scsi_Device *) scsi_init_malloc(sizeof(Scsi_Device), GFP_ATOMIC);
- *SDpnt2 = SDpnt;
- if (!SDpnt) {
- printk("scsi: scan_scsis_single: Cannot malloc\n");
- return 0;
- }
- /*
- * Register the queue for the device. All I/O requests will come
- * in through here. We also need to register a pointer to
- * ourselves, since the queue handler won't know what device
- * the queue actually represents. We could look it up, but it
- * is pointless work.
- */
- blk_init_queue(&SDpnt->request_queue, scsi_request_fn);
- blk_queue_headactive(&SDpnt->request_queue, 0);
- SDpnt->request_queue.queuedata = (void *) SDpnt;
- SDpnt->host = shpnt;
- initialize_merge_fn(SDpnt);
-
- /*
- * And hook up our command block to the new device we will be testing
- * for.
- */
- SDpnt->device_queue = SCpnt;
- SDpnt->online = TRUE;
-
- /*
- * Initialize the object that we will use to wait for command blocks.
- */
- init_waitqueue_head(&SDpnt->scpnt_wait);
-
- /*
- * Since we just found one device, there had damn well better be one in the list
- * already.
- */
- if (shpnt->host_queue == NULL)
- panic("scan_scsis_single: Host queue == NULL\n");
-
- SDtail = shpnt->host_queue;
- while (SDtail->next) {
- SDtail = SDtail->next;
- }
-
- /* Add this device to the linked list at the end */
- SDtail->next = SDpnt;
- SDpnt->prev = SDtail;
- SDpnt->next = NULL;
-
- /*
- * Some scsi devices cannot be polled for lun != 0 due to firmware bugs
- */
- if (bflags & BLIST_NOLUN)
- return 0; /* break; */
-
- /*
- * If this device is known to support sparse multiple units, override the
- * other settings, and scan all of them.
- */
- if (bflags & BLIST_SPARSELUN) {
- *max_dev_lun = 8;
- *sparse_lun = 1;
- return 1;
- }
- /*
- * If this device is known to support multiple units, override the other
- * settings, and scan all of them.
- */
- if (bflags & BLIST_FORCELUN) {
- *max_dev_lun = 8;
- return 1;
- }
- /*
- * REGAL CDC-4X: avoid hang after LUN 4
- */
- if (bflags & BLIST_MAX5LUN) {
- *max_dev_lun = 5;
- return 1;
- }
-
- /*
- * If this device is Ghosted, scan upto two luns. (It physically only
- * has one). -- REW
- */
- if (bflags & BLIST_GHOST) {
- *max_dev_lun = 2;
- return 1;
- }
-
-
- /*
- * We assume the device can't handle lun!=0 if: - it reports scsi-0 (ANSI
- * SCSI Revision 0) (old drives like MAXTOR XT-3280) or - it reports scsi-1
- * (ANSI SCSI Revision 1) and Response Data Format 0
- */
- if (((scsi_result[2] & 0x07) == 0)
- ||
- ((scsi_result[2] & 0x07) == 1 &&
- (scsi_result[3] & 0x0f) == 0))
- return 0;
- return 1;
-}
-
-/*
- * Flag bits for the internal_timeout array
- */
-#define NORMAL_TIMEOUT 0
-#define IN_ABORT 1
-#define IN_RESET 2
-#define IN_RESET2 4
-#define IN_RESET3 8
-
-
-/*
* This lock protects the freelist for all devices on the system.
* We could make this finer grained by having a single lock per
* device if it is ever found that there is excessive contention
@@ -990,11 +245,6 @@
static spinlock_t device_request_lock = SPIN_LOCK_UNLOCKED;
/*
- * Used for access to internal allocator used for DMA safe buffers.
- */
-static spinlock_t allocator_request_lock = SPIN_LOCK_UNLOCKED;
-
-/*
* Used to protect insertion into and removal from the queue of
* commands to be processed by the bottom half handler.
*/
@@ -1465,7 +715,8 @@
* the completion function for the high level driver.
*/
- memcpy((void *) SCpnt->data_cmnd, (const void *) cmnd, 12);
+ memcpy((void *) SCpnt->data_cmnd, (const void *) cmnd,
+ sizeof(SCpnt->data_cmnd));
SCpnt->reset_chain = NULL;
SCpnt->serial_number = 0;
SCpnt->serial_number_at_timeout = 0;
@@ -1477,7 +728,8 @@
SCpnt->done = done;
SCpnt->timeout_per_command = timeout;
- memcpy((void *) SCpnt->cmnd, (const void *) cmnd, 12);
+ memcpy((void *) SCpnt->cmnd, (const void *) cmnd,
+ sizeof(SCpnt->cmnd));
/* Zero the sense buffer. Some host adapters automatically request
* sense on error. 0 is not a valid sense code.
*/
@@ -1820,127 +1072,6 @@
static void scsi_unregister_host(Scsi_Host_Template *);
#endif
-/*
- * Function: scsi_malloc
- *
- * Purpose: Allocate memory from the DMA-safe pool.
- *
- * Arguments: len - amount of memory we need.
- *
- * Lock status: No locks assumed to be held. This function is SMP-safe.
- *
- * Returns: Pointer to memory block.
- *
- * Notes: Prior to the new queue code, this function was not SMP-safe.
- * This function can only allocate in units of sectors
- * (i.e. 512 bytes).
- *
- * We cannot use the normal system allocator becuase we need
- * to be able to guarantee that we can process a complete disk
- * I/O request without touching the system allocator. Think
- * about it - if the system were heavily swapping, and tried to
- * write out a block of memory to disk, and the SCSI code needed
- * to allocate more memory in order to be able to write the
- * data to disk, you would wedge the system.
- */
-void *scsi_malloc(unsigned int len)
-{
- unsigned int nbits, mask;
- unsigned long flags;
-
- int i, j;
- if (len % SECTOR_SIZE != 0 || len > PAGE_SIZE)
- return NULL;
-
- nbits = len >> 9;
- mask = (1 << nbits) - 1;
-
- spin_lock_irqsave(&allocator_request_lock, flags);
-
- for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++)
- for (j = 0; j <= SECTORS_PER_PAGE - nbits; j++) {
- if ((dma_malloc_freelist[i] & (mask << j)) == 0) {
- dma_malloc_freelist[i] |= (mask << j);
- scsi_dma_free_sectors -= nbits;
-#ifdef DEBUG
- SCSI_LOG_MLQUEUE(3, printk("SMalloc: %d %p [From:%p]\n", len, dma_malloc_pages[i] + (j << 9)));
- printk("SMalloc: %d %p [From:%p]\n", len, dma_malloc_pages[i] + (j << 9));
-#endif
- spin_unlock_irqrestore(&allocator_request_lock, flags);
- return (void *) ((unsigned long) dma_malloc_pages[i] + (j << 9));
- }
- }
- spin_unlock_irqrestore(&allocator_request_lock, flags);
- return NULL; /* Nope. No more */
-}
-
-/*
- * Function: scsi_free
- *
- * Purpose: Free memory into the DMA-safe pool.
- *
- * Arguments: ptr - data block we are freeing.
- * len - size of block we are freeing.
- *
- * Lock status: No locks assumed to be held. This function is SMP-safe.
- *
- * Returns: Nothing
- *
- * Notes: This function *must* only be used to free memory
- * allocated from scsi_malloc().
- *
- * Prior to the new queue code, this function was not SMP-safe.
- * This function can only allocate in units of sectors
- * (i.e. 512 bytes).
- */
-int scsi_free(void *obj, unsigned int len)
-{
- unsigned int page, sector, nbits, mask;
- unsigned long flags;
-
-#ifdef DEBUG
- unsigned long ret = 0;
-
-#ifdef __mips__
- __asm__ __volatile__("move\t%0,$31":"=r"(ret));
-#else
- ret = __builtin_return_address(0);
-#endif
- printk("scsi_free %p %d\n", obj, len);
- SCSI_LOG_MLQUEUE(3, printk("SFree: %p %d\n", obj, len));
-#endif
-
- spin_lock_irqsave(&allocator_request_lock, flags);
-
- for (page = 0; page < dma_sectors / SECTORS_PER_PAGE; page++) {
- unsigned long page_addr = (unsigned long) dma_malloc_pages[page];
- if ((unsigned long) obj >= page_addr &&
- (unsigned long) obj < page_addr + PAGE_SIZE) {
- sector = (((unsigned long) obj) - page_addr) >> 9;
-
- nbits = len >> 9;
- mask = (1 << nbits) - 1;
-
- if ((mask << sector) >= (1 << SECTORS_PER_PAGE))
- panic("scsi_free:Bad memory alignment");
-
- if ((dma_malloc_freelist[page] &
- (mask << sector)) != (mask << sector)) {
-#ifdef DEBUG
- printk("scsi_free(obj=%p, len=%d) called from %08lx\n",
- obj, len, ret);
-#endif
- panic("scsi_free:Trying to free unused memory");
- }
- scsi_dma_free_sectors += nbits;
- dma_malloc_freelist[page] &= ~(mask << sector);
- spin_unlock_irqrestore(&allocator_request_lock, flags);
- return 0;
- }
- }
- panic("scsi_free:Bad offset");
-}
-
int scsi_loadable_module_flag; /* Set after we scan builtin drivers */
@@ -2124,7 +1255,7 @@
/*
* This should build the DMA pool.
*/
- resize_dma_pool();
+ scsi_resize_dma_pool();
/*
* OK, now we finish the initialization by doing spin-up, read
@@ -2140,47 +1271,6 @@
}
#endif /* MODULE */ /* } */
-static void print_inquiry(unsigned char *data)
-{
- int i;
-
- printk(" Vendor: ");
- for (i = 8; i < 16; i++) {
- if (data[i] >= 0x20 && i < data[4] + 5)
- printk("%c", data[i]);
- else
- printk(" ");
- }
-
- printk(" Model: ");
- for (i = 16; i < 32; i++) {
- if (data[i] >= 0x20 && i < data[4] + 5)
- printk("%c", data[i]);
- else
- printk(" ");
- }
-
- printk(" Rev: ");
- for (i = 32; i < 36; i++) {
- if (data[i] >= 0x20 && i < data[4] + 5)
- printk("%c", data[i]);
- else
- printk(" ");
- }
-
- printk("\n");
-
- i = data[0] & 0x1f;
-
- printk(" Type: %s ",
- i < MAX_SCSI_DEVICE_CODE ? scsi_device_types[i] : "Unknown ");
- printk(" ANSI SCSI revision: %02x", data[2] & 0x07);
- if ((data[2] & 0x07) == 1 && (data[3] & 0x0f) == 1)
- printk(" CCS\n");
- else
- printk("\n");
-}
-
#ifdef CONFIG_PROC_FS
static int scsi_proc_info(char *buffer, char **start, off_t offset, int length)
{
@@ -2475,217 +1565,6 @@
}
#endif
-/*
- * Function: resize_dma_pool
- *
- * Purpose: Ensure that the DMA pool is sufficiently large to be
- * able to guarantee that we can always process I/O requests
- * without calling the system allocator.
- *
- * Arguments: None.
- *
- * Lock status: No locks assumed to be held. This function is SMP-safe.
- *
- * Returns: Nothing
- *
- * Notes: Prior to the new queue code, this function was not SMP-safe.
- * Go through the device list and recompute the most appropriate
- * size for the dma pool. Then grab more memory (as required).
- */
-static void resize_dma_pool(void)
-{
- int i, k;
- unsigned long size;
- unsigned long flags;
- struct Scsi_Host *shpnt;
- struct Scsi_Host *host = NULL;
- Scsi_Device *SDpnt;
- FreeSectorBitmap *new_dma_malloc_freelist = NULL;
- unsigned int new_dma_sectors = 0;
- unsigned int new_need_isa_buffer = 0;
- unsigned char **new_dma_malloc_pages = NULL;
- int out_of_space = 0;
-
- spin_lock_irqsave(&allocator_request_lock, flags);
-
- if (!scsi_hostlist) {
- /*
- * Free up the DMA pool.
- */
- if (scsi_dma_free_sectors != dma_sectors)
- panic("SCSI DMA pool memory leak %d %d\n", scsi_dma_free_sectors, dma_sectors);
-
- for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++)
- scsi_init_free(dma_malloc_pages[i], PAGE_SIZE);
- if (dma_malloc_pages)
- scsi_init_free((char *) dma_malloc_pages,
- (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages));
- dma_malloc_pages = NULL;
- if (dma_malloc_freelist)
- scsi_init_free((char *) dma_malloc_freelist,
- (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_freelist));
- dma_malloc_freelist = NULL;
- dma_sectors = 0;
- scsi_dma_free_sectors = 0;
- spin_unlock_irqrestore(&allocator_request_lock, flags);
- return;
- }
- /* Next, check to see if we need to extend the DMA buffer pool */
-
- new_dma_sectors = 2 * SECTORS_PER_PAGE; /* Base value we use */
-
- if (__pa(high_memory) - 1 > ISA_DMA_THRESHOLD)
- need_isa_bounce_buffers = 1;
- else
- need_isa_bounce_buffers = 0;
-
- if (scsi_devicelist)
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next)
- new_dma_sectors += SECTORS_PER_PAGE; /* Increment for each host */
-
- for (host = scsi_hostlist; host; host = host->next) {
- for (SDpnt = host->host_queue; SDpnt; SDpnt = SDpnt->next) {
- /*
- * sd and sr drivers allocate scatterlists.
- * sr drivers may allocate for each command 1x2048 or 2x1024 extra
- * buffers for 2k sector size and 1k fs.
- * sg driver allocates buffers < 4k.
- * st driver does not need buffers from the dma pool.
- * estimate 4k buffer/command for devices of unknown type (should panic).
- */
- if (SDpnt->type == TYPE_WORM || SDpnt->type == TYPE_ROM ||
- SDpnt->type == TYPE_DISK || SDpnt->type == TYPE_MOD) {
- new_dma_sectors += ((host->sg_tablesize *
- sizeof(struct scatterlist) + 511) >> 9) *
- SDpnt->queue_depth;
- if (SDpnt->type == TYPE_WORM || SDpnt->type == TYPE_ROM)
- new_dma_sectors += (2048 >> 9) * SDpnt->queue_depth;
- } else if (SDpnt->type == TYPE_SCANNER ||
- SDpnt->type == TYPE_PROCESSOR ||
- SDpnt->type == TYPE_MEDIUM_CHANGER ||
- SDpnt->type == TYPE_ENCLOSURE) {
- new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth;
- } else {
- if (SDpnt->type != TYPE_TAPE) {
- printk("resize_dma_pool: unknown device type %d\n", SDpnt->type);
- new_dma_sectors += (4096 >> 9) * SDpnt->queue_depth;
- }
- }
-
- if (host->unchecked_isa_dma &&
- need_isa_bounce_buffers &&
- SDpnt->type != TYPE_TAPE) {
- new_dma_sectors += (PAGE_SIZE >> 9) * host->sg_tablesize *
- SDpnt->queue_depth;
- new_need_isa_buffer++;
- }
- }
- }
-
-#ifdef DEBUG_INIT
- printk("resize_dma_pool: needed dma sectors = %d\n", new_dma_sectors);
-#endif
-
- /* limit DMA memory to 32MB: */
- new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
-
- /*
- * We never shrink the buffers - this leads to
- * race conditions that I would rather not even think
- * about right now.
- */
-#if 0 /* Why do this? No gain and risks out_of_space */
- if (new_dma_sectors < dma_sectors)
- new_dma_sectors = dma_sectors;
-#endif
- if (new_dma_sectors <= dma_sectors) {
- spin_unlock_irqrestore(&allocator_request_lock, flags);
- return; /* best to quit while we are in front */
- }
-
- for (k = 0; k < 20; ++k) { /* just in case */
- out_of_space = 0;
- size = (new_dma_sectors / SECTORS_PER_PAGE) *
- sizeof(FreeSectorBitmap);
- new_dma_malloc_freelist = (FreeSectorBitmap *)
- scsi_init_malloc(size, GFP_ATOMIC);
- if (new_dma_malloc_freelist) {
- size = (new_dma_sectors / SECTORS_PER_PAGE) *
- sizeof(*new_dma_malloc_pages);
- new_dma_malloc_pages = (unsigned char **)
- scsi_init_malloc(size, GFP_ATOMIC);
- if (!new_dma_malloc_pages) {
- size = (new_dma_sectors / SECTORS_PER_PAGE) *
- sizeof(FreeSectorBitmap);
- scsi_init_free((char *) new_dma_malloc_freelist, size);
- out_of_space = 1;
- }
- } else
- out_of_space = 1;
-
- if ((!out_of_space) && (new_dma_sectors > dma_sectors)) {
- for (i = dma_sectors / SECTORS_PER_PAGE;
- i < new_dma_sectors / SECTORS_PER_PAGE; i++) {
- new_dma_malloc_pages[i] = (unsigned char *)
- scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
- if (!new_dma_malloc_pages[i])
- break;
- }
- if (i != new_dma_sectors / SECTORS_PER_PAGE) { /* clean up */
- int k = i;
-
- out_of_space = 1;
- for (i = 0; i < k; ++i)
- scsi_init_free(new_dma_malloc_pages[i], PAGE_SIZE);
- }
- }
- if (out_of_space) { /* try scaling down new_dma_sectors request */
- printk("scsi::resize_dma_pool: WARNING, dma_sectors=%u, "
- "wanted=%u, scaling\n", dma_sectors, new_dma_sectors);
- if (new_dma_sectors < (8 * SECTORS_PER_PAGE))
- break; /* pretty well hopeless ... */
- new_dma_sectors = (new_dma_sectors * 3) / 4;
- new_dma_sectors = (new_dma_sectors + 15) & 0xfff0;
- if (new_dma_sectors <= dma_sectors)
- break; /* stick with what we have got */
- } else
- break; /* found space ... */
- } /* end of for loop */
- if (out_of_space) {
- spin_unlock_irqrestore(&allocator_request_lock, flags);
- scsi_need_isa_buffer = new_need_isa_buffer; /* some useful info */
- printk(" WARNING, not enough memory, pool not expanded\n");
- return;
- }
- /* When we dick with the actual DMA list, we need to
- * protect things
- */
- if (dma_malloc_freelist) {
- size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(FreeSectorBitmap);
- memcpy(new_dma_malloc_freelist, dma_malloc_freelist, size);
- scsi_init_free((char *) dma_malloc_freelist, size);
- }
- dma_malloc_freelist = new_dma_malloc_freelist;
-
- if (dma_malloc_pages) {
- size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages);
- memcpy(new_dma_malloc_pages, dma_malloc_pages, size);
- scsi_init_free((char *) dma_malloc_pages, size);
- }
- scsi_dma_free_sectors += new_dma_sectors - dma_sectors;
- dma_malloc_pages = new_dma_malloc_pages;
- dma_sectors = new_dma_sectors;
- scsi_need_isa_buffer = new_need_isa_buffer;
-
- spin_unlock_irqrestore(&allocator_request_lock, flags);
-
-#ifdef DEBUG_INIT
- printk("resize_dma_pool: dma free sectors = %d\n", scsi_dma_free_sectors);
- printk("resize_dma_pool: dma sectors = %d\n", dma_sectors);
- printk("resize_dma_pool: need isa buffers = %d\n", scsi_need_isa_buffer);
-#endif
-}
-
#ifdef CONFIG_MODULES /* a big #ifdef block... */
/*
@@ -2819,7 +1698,7 @@
* Now that we have all of the devices, resize the DMA pool,
* as required. */
if (!out_of_space)
- resize_dma_pool();
+ scsi_resize_dma_pool();
/* This does any final handling that is required. */
@@ -3037,7 +1916,7 @@
* do the right thing and free everything.
*/
if (!scsi_hosts)
- resize_dma_pool();
+ scsi_resize_dma_pool();
printk("scsi : %d host%s.\n", next_scsi_host,
(next_scsi_host == 1) ? "" : "s");
@@ -3049,7 +1928,6 @@
(scsi_memory_upper_value - scsi_init_memory_start) / 1024);
#endif
-
/* There were some hosts that were loaded at boot time, so we cannot
do any more than this */
if (tpnt->present)
@@ -3132,7 +2010,7 @@
if (tpnt->finish && tpnt->nr_dev)
(*tpnt->finish) ();
if (!out_of_space)
- resize_dma_pool();
+ scsi_resize_dma_pool();
MOD_INC_USE_COUNT;
if (out_of_space) {
@@ -3362,6 +2240,11 @@
int has_space = 0;
struct proc_dir_entry *generic;
+ if( scsi_init_minimal_dma_pool() != 0 )
+ {
+ return 1;
+ }
+
/*
* This makes /proc/scsi and /proc/scsi/scsi visible.
*/
@@ -3382,39 +2265,6 @@
scsi_loadable_module_flag = 1;
- dma_sectors = PAGE_SIZE / SECTOR_SIZE;
- scsi_dma_free_sectors = dma_sectors;
- /*
- * Set up a minimal DMA buffer list - this will be used during scan_scsis
- * in some cases.
- */
-
- /* One bit per sector to indicate free/busy */
- size = (dma_sectors / SECTORS_PER_PAGE) * sizeof(FreeSectorBitmap);
- dma_malloc_freelist = (FreeSectorBitmap *)
- scsi_init_malloc(size, GFP_ATOMIC);
- if (dma_malloc_freelist) {
- /* One pointer per page for the page list */
- dma_malloc_pages = (unsigned char **) scsi_init_malloc(
- (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages),
- GFP_ATOMIC);
- if (dma_malloc_pages) {
- dma_malloc_pages[0] = (unsigned char *)
- scsi_init_malloc(PAGE_SIZE, GFP_ATOMIC | GFP_DMA);
- if (dma_malloc_pages[0])
- has_space = 1;
- }
- }
- if (!has_space) {
- if (dma_malloc_freelist) {
- scsi_init_free((char *) dma_malloc_freelist, size);
- if (dma_malloc_pages)
- scsi_init_free((char *) dma_malloc_pages,
- (dma_sectors / SECTORS_PER_PAGE) * sizeof(*dma_malloc_pages));
- }
- printk("scsi::init_module: failed, out of memory\n");
- return 1;
- }
/*
* This is where the processing takes place for most everything
* when commands are completed.
@@ -3437,7 +2287,7 @@
/*
* Free up the DMA pool.
*/
- resize_dma_pool();
+ scsi_resize_dma_pool();
}
@@ -3491,7 +2341,7 @@
SDpnt->device_queue = SCpnt;
- blk_init_queue(&SDpnt->request_queue, scsi_request_fn);
+ blk_init_queue(&SDpnt->request_queue, scsi_get_request_handler(SDpnt, SDpnt->host));
blk_queue_headactive(&SDpnt->request_queue, 0);
SDpnt->request_queue.queuedata = (void *) SDpnt;
@@ -3519,7 +2369,7 @@
*/
void scsi_free_host_dev(Scsi_Device * SDpnt)
{
- if( SDpnt->id != SDpnt->host->this_id )
+ if( (unsigned char) SDpnt->id != (unsigned char) SDpnt->host->this_id )
{
panic("Attempt to delete wrong device\n");
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)