--- linux-2.2.12/fs/devices.c.orig Wed Dec 23 20:39:49 1998 +++ linux-2.2.12/fs/devices.c Fri Aug 27 11:36:48 1999 @@ -370,3 +370,13 @@ sprintf(buffer, "%s(%d,%d)", name, MAJOR(dev), MINOR(dev)); return buffer; } + +struct file_operations * is_reg_blkdev(unsigned int major) +{ + return blkdevs[major].fops; +} + +struct file_operations * is_reg_chrdev(unsigned int major) +{ + return chrdevs[major].fops; +} --- linux-2.2.12/kernel/ksyms.c.orig Mon Aug 9 21:04:41 1999 +++ linux-2.2.12/kernel/ksyms.c Fri Aug 27 11:34:14 1999 @@ -196,8 +196,10 @@ /* device registration */ EXPORT_SYMBOL(register_chrdev); EXPORT_SYMBOL(unregister_chrdev); +EXPORT_SYMBOL(is_reg_chrdev); EXPORT_SYMBOL(register_blkdev); EXPORT_SYMBOL(unregister_blkdev); +EXPORT_SYMBOL(is_reg_blkdev); EXPORT_SYMBOL(tty_register_driver); EXPORT_SYMBOL(tty_unregister_driver); EXPORT_SYMBOL(tty_std_termios); --- linux-2.2.12/include/linux/fs.h.orig Fri Aug 27 01:53:30 1999 +++ linux-2.2.12/include/linux/fs.h Fri Aug 27 11:34:44 1999 @@ -728,7 +728,8 @@ extern char * bdevname(kdev_t dev); extern char * cdevname(kdev_t dev); extern char * kdevname(kdev_t dev); - +extern struct file_operations * is_reg_blkdev(unsigned int major); +extern struct file_operations * is_reg_chrdev(unsigned int major); extern void init_fifo(struct inode * inode); extern struct inode_operations fifo_inode_operations; --- linux-2.2.12/drivers/scsi/scsi.c.orig Mon Aug 9 21:04:40 1999 +++ linux-2.2.12/drivers/scsi/scsi.c Fri Aug 27 15:33:31 1999 @@ -34,6 +34,10 @@ * Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli * * out_of_space + add-single-device work, D. Gilbert (dpg) 990612 + * + * Call init regardless of dev_noticed and have the s?_init() handle it + * and unregister in case of failure. Similar for host adapters. + * Fixed module counters. garloff@suse.de 990827 */ #include @@ -2709,13 +2713,19 @@ else tpnt->present = tpnt->detect(tpnt); - if (tpnt->present) + /* No need to clean up. The host should scsi_unregister() if + * detect() called scsi_register() before but detection failed. */ + if (!tpnt->present) + return 1; + else { + MOD_INC_USE_COUNT; if(pcount == next_scsi_host) { if(tpnt->present > 1) { printk("Failure to register low-level scsi driver"); + __MOD_DEC_USE_COUNT(tpnt->module); scsi_unregister_host(tpnt); return 1; } @@ -2723,6 +2733,7 @@ * The low-level driver failed to register a driver. We * can do this now. */ + printk("Register driver for host %s\n", tpnt->name); scsi_register(tpnt,0); } tpnt->next = scsi_hosts; /* Add to the linked list */ @@ -2841,9 +2852,8 @@ (scsi_memory_upper_value - scsi_init_memory_start) / 1024); #endif - MOD_INC_USE_COUNT; - if (out_of_space) { + __MOD_DEC_USE_COUNT(tpnt->module); scsi_unregister_host(tpnt); /* easiest way to clean up?? */ return 1; } @@ -3114,6 +3124,7 @@ if (tpnt->next) return 1; scsi_register_device(tpnt); + MOD_INC_USE_COUNT; /* * First scan the devices that we know about, and see if we notice them. */ @@ -3131,8 +3142,13 @@ * If any of the devices would match this driver, then perform the * init function. */ - if(tpnt->init && tpnt->dev_noticed) - if ((*tpnt->init)()) return 1; + if(tpnt->init) + if ((*tpnt->init)()) + { + __MOD_DEC_USE_COUNT(tpnt->module); + scsi_unregister_device (tpnt); + return 1; + } /* * Now actually connect the devices to the new driver. @@ -3163,9 +3179,9 @@ if(tpnt->finish && tpnt->nr_dev) (*tpnt->finish)(); if (! out_of_space) resize_dma_pool(); - MOD_INC_USE_COUNT; if (out_of_space) { + __MOD_DEC_USE_COUNT(tpnt->module); scsi_unregister_device(tpnt); /* easiest way to clean up?? */ return 1; } @@ -3318,6 +3334,7 @@ struct Scsi_Host * shpnt; Scsi_Cmnd * SCpnt; Scsi_Device * SDpnt; + struct Scsi_Device_Template * sdtpnt; printk("Dump of scsi host parameters:\n"); i = 0; for(shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) @@ -3341,7 +3358,7 @@ for(SCpnt=SDpnt->device_queue; SCpnt; SCpnt = SCpnt->next) { /* (0) h:c:t:l (dev sect nsect cnumsec sg) (ret all flg) (to/cmd to ito) cmd snse result %d %x */ - printk("(%3d) %2d:%1d:%2d:%2d (%6s %4ld %4ld %4ld %4x %1d) (%1d %1d 0x%2x) (%4d %4d %4d) 0x%2.2x 0x%2.2x 0x%8.8x\n", + printk("(%3d) %2d:%1d:%2d:%2d (%6s %4ld %4ld %4ld %4x %1d) (%1d %1d 0x%2.2x) (%4d %4d %4d) 0x%2.2x 0x%2.2x 0x%8.8x\n", i++, SCpnt->host ? SCpnt->host->host_no : -1, @@ -3400,6 +3417,15 @@ } } printk("wait_for_request = %p\n", wait_for_request); + sdtpnt = scsi_devicelist; + printk("SCSI List of Device Templates: %p", sdtpnt); + while (sdtpnt) + { + printk ("(%s)->%p", sdtpnt->tag, sdtpnt->next); + sdtpnt = sdtpnt->next; + } + printk ("\n"); + #endif /* CONFIG_SCSI_LOGGING */ /* } */ #endif /* CONFIG_PROC_FS */ } --- linux-2.2.12/drivers/scsi/sd.c.orig Mon Aug 9 21:05:05 1999 +++ linux-2.2.12/drivers/scsi/sd.c Fri Aug 27 13:39:10 1999 @@ -1494,6 +1494,11 @@ { int i; + if(!sd_registered && is_reg_blkdev(SD_MAJOR(0))) { + printk("Unable to get major %d for SCSI disk\n", SD_MAJOR(0)); + return 1; + } + if (sd_template.dev_noticed == 0) return 0; if (!rscsi_disks) --- linux-2.2.12/drivers/scsi/sr.c.orig Fri Jan 15 23:41:04 1999 +++ linux-2.2.12/drivers/scsi/sr.c Fri Aug 27 13:43:26 1999 @@ -1014,14 +1014,16 @@ static int sr_init() { int i; + + if (!sr_registered && is_reg_blkdev(SCSI_CDROM_MAJOR)) { + printk("Unable to get major %d for SCSI-CD\n",SCSI_CDROM_MAJOR); + return 1; + } if(sr_template.dev_noticed == 0) return 0; if(!sr_registered) { - if (register_blkdev(MAJOR_NR,"sr",&cdrom_fops)) { - printk("Unable to get major %d for SCSI-CD\n",MAJOR_NR); - return 1; - } + register_blkdev(SCSI_CDROM_MAJOR,"sr",&cdrom_fops); sr_registered++; } --- linux-2.2.12/drivers/scsi/sg.c.orig Tue Jun 8 01:27:06 1999 +++ linux-2.2.12/drivers/scsi/sg.c Fri Aug 27 15:35:16 1999 @@ -113,7 +113,7 @@ static void sg_detach(Scsi_Device *); -struct Scsi_Device_Template sg_template = {NULL, NULL, "sg", NULL, 0xff, +struct Scsi_Device_Template sg_template = {NULL, "generic", "sg", NULL, 0xff, SCSI_GENERIC_MAJOR, 0, 0, 0, 0, sg_detect, sg_init, sg_finish, sg_attach, sg_detach}; @@ -948,16 +948,17 @@ static int sg_init() { static int sg_registered = 0; + + if(!sg_registered && is_reg_chrdev(SCSI_GENERIC_MAJOR)) { + printk("Unable to get major %d for generic SCSI device\n", + SCSI_GENERIC_MAJOR); + return 1; + } if (sg_template.dev_noticed == 0) return 0; if(!sg_registered) { - if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops)) - { - printk("Unable to get major %d for generic SCSI device\n", - SCSI_GENERIC_MAJOR); - return 1; - } + register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops); sg_registered++; } --- linux-2.2.12/drivers/scsi/st.c.orig Sat May 22 23:51:26 1999 +++ linux-2.2.12/drivers/scsi/st.c Fri Aug 27 13:41:28 1999 @@ -3453,13 +3453,15 @@ int target_nbr; #endif + if(!st_registered && is_reg_chrdev(SCSI_TAPE_MAJOR)) { + printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",SCSI_TAPE_MAJOR); + return 1; + } + if (st_template.dev_noticed == 0) return 0; if(!st_registered) { - if (register_chrdev(SCSI_TAPE_MAJOR,"st",&st_fops)) { - printk(KERN_ERR "Unable to get major %d for SCSI tapes\n",MAJOR_NR); - return 1; - } + register_chrdev(SCSI_TAPE_MAJOR,"st",&st_fops); st_registered++; }