}
}
-static struct gendisk mfm_gendisk = {
+static struct gendisk mfm_gendisk[2] = {
+{
major: MAJOR_NR,
+ first_minor: 0,
major_name: "mfm",
minor_shift: 6,
part: mfm,
+},
+{
+ major: MAJOR_NR,
+ first_minor: 64,
+ major_name: "mfm",
+ minor_shift: 6,
+ part: mfm + 64,
};
static struct block_device_operations mfm_fops =
printk("mfm: detected %d hard drive%s\n", mfm_drives,
mfm_drives == 1 ? "" : "s");
- mfm_gendisk.nr_real = mfm_drives;
-
if (request_irq(mfm_irq, mfm_interrupt_handler, SA_INTERRUPT, "MFM harddisk", NULL))
printk("mfm: unable to get IRQ%d\n", mfm_irq);
outw(0x80, mfm_irqenable); /* Required to enable IRQs from MFM podule */
for (i = 0; i < mfm_drives; i++) {
+ mfm_gendisk[i].nr_real = 1;
+ add_gendisk(mfm_gendisk + i);
mfm_geometry (i);
- register_disk(&mfm_gendisk, mk_kdev(MAJOR_NR,i<<6), 1<<6,
+ register_disk(mfm_gendisk + i, mk_kdev(MAJOR_NR,i<<6), 1<<6,
&mfm_fops,
mfm_info[i].cylinders * mfm_info[i].heads *
mfm_info[i].sectors / 2);
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_mfm_request);
- add_gendisk(&mfm_gendisk);
-
Busy = 0;
lastspecifieddrive = -1;
void cleanup_module(void)
{
+ int i;
if (ecs && mfm_irqenable)
outw (0, mfm_irqenable); /* Required to enable IRQs from MFM podule */
free_irq(mfm_irq, NULL);
unregister_blkdev(MAJOR_NR, "mfm");
- del_gendisk(&mfm_gendisk);
+ for (i = 0; i < mfm_drives; i++)
+ del_gendisk(mfm_gendisk + i);
if (ecs)
ecard_release(ecs);
if (mfm_addr)
{
if (sgp == gp)
{
-// printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
-// sgp->major)
+ printk(KERN_ERR "add_gendisk: device major %d is buggy and added a live gendisk!\n",
+ sgp->major)
goto out;
}
}
int alt_geom;
int present;
char name[PD_NAMELEN]; /* pda, pdb, etc ... */
+ struct gendisk gd;
};
struct pd_unit pd[PD_UNITS];
major: PD_MAJOR,
major_name: PD_NAME,
minor_shift: PD_BITS,
- part: pd_hd,
fops: &pd_fops,
+ nr_real: 1,
};
static struct block_device_operations pd_fops = {
}
static int pd_detect( void )
-
-{ int k, unit;
+{
+ int k, unit;
k = 0;
if (pd_drive_count == 0) { /* nothing spec'd - so autoprobe for 1 */
k = unit+1;
} else pi_release(PI);
}
- for (unit=0;unit<PD_UNITS;unit++)
- register_disk(&pd_gendisk,mk_kdev(MAJOR_NR,unit<<PD_BITS),
- PD_PARTNS,&pd_fops,
- PD.present?PD.capacity:0);
-
-/* We lie about the number of drives found, as the generic partition
- scanner assumes that the drives are numbered sequentially from 0.
- This can result in some bogus error messages if non-sequential
- drive numbers are used.
-*/
+ for (unit=0;unit<PD_UNITS;unit++) {
+ if (PD.present) {
+ PD.gd = pd_gendisk;
+ PD.gd.first_minor = unit << PD_BITS;
+ PD.gd.part = pd_hd + (unit << PD_BITS);
+ add_gendisk(&PD.gd);
+ register_disk(&PD.gd,mk_kdev(MAJOR_NR,unit<<PD_BITS),
+ PD_PARTNS,&pd_fops,
+ PD.capacity);
+ }
+ }
if (k)
- return k;
+ return 1;
printk("%s: no valid drive found\n",name);
return 0;
}
static int __init pd_init(void)
{
request_queue_t * q;
- int unit;
-
if (disable) return -1;
if (register_blkdev(MAJOR_NR,name,&pd_fops)) {
printk("%s: unable to get major number %d\n",
pd_gendisk.major = major;
pd_gendisk.major_name = name;
- add_gendisk(&pd_gendisk);
-
printk("%s: %s version %s, major %d, cluster %d, nice %d\n",
name,name,PD_VERSION,major,cluster,nice);
pd_init_units();
- pd_gendisk.nr_real = pd_detect();
- if (!pd_gendisk.nr_real) {
+ if (!pd_detect()) {
unregister_blkdev(MAJOR_NR, name);
- del_gendisk(&pd_gendisk);
- for (unit=0; unit<PD_UNITS; unit++)
- if (PD.present)
- pi_release(PI);
return -1;
}
return 0;
{
int unit;
unregister_blkdev(MAJOR_NR, name);
- del_gendisk(&pd_gendisk);
for (unit=0; unit<PD_UNITS; unit++)
- if (PD.present)
+ if (PD.present) {
+ del_gendisk(&PD.gd);
pi_release(PI);
+ }
}
MODULE_LICENSE("GPL");
extern struct block_device_operations hd_fops;
-static struct gendisk hd_gendisk = {
+static struct gendisk hd_gendisk[2] = {
+{
.major = MAJOR_NR,
+ .first_minor = 0,
.major_name = "hd",
.minor_shift = 6,
.part = hd,
.fops = &hd_fops,
+},{
+ .major = MAJOR_NR,
+ .first_minor = 64,
+ .major_name = "hd",
+ .minor_shift = 6,
+ .part = hd + 64,
+ .fops = &hd_fops,
+}
};
static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return;
}
- hd_gendisk.nr_real = NR_HD;
-
- for(drive=0; drive < NR_HD; drive++)
- register_disk(&hd_gendisk, mk_kdev(MAJOR_NR,drive<<6), 1<<6,
+ for(drive=0; drive < NR_HD; drive++) {
+ hd_gendisk[i].nr_real = 1;
+ add_gendisk(hd_gendisk + drive);
+ register_disk(hd_gendisk + drive,
+ mk_kdev(MAJOR_NR,drive<<6), 1<<6,
&hd_fops, hd_info[drive].head * hd_info[drive].sect *
hd_info[drive].cyl);
+ }
}
int __init hd_init(void)
}
blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_hd_request, &hd_lock);
blk_queue_max_sectors(BLK_DEFAULT_QUEUE(MAJOR_NR), 255);
- add_gendisk(&hd_gendisk);
init_timer(&device_timer);
device_timer.function = hd_times_out;
hd_geninit();
if (drive != &ch->drives[i])
continue;
drvid = i;
- ch->gd->de_arr[i] = drive->de;
+ ch->gd[i]->de_arr[0] = drive->de;
if (drive->removable)
- ch->gd->flags[i] |= GENHD_FL_REMOVABLE;
+ ch->gd[i]->flags[0] |= GENHD_FL_REMOVABLE;
break;
}
struct ata_channel *hwif = drive->channel;
if (drive != &hwif->drives[i]) continue;
- hwif->gd->de_arr[i] = drive->de;
+ hwif->gd[i]->de_arr[0] = drive->de;
if (drive->removable)
- hwif->gd->flags[i] |= GENHD_FL_REMOVABLE;
+ hwif->gd[i]->flags[0] |= GENHD_FL_REMOVABLE;
break;
}
}
blk_dev[ch->major].data = NULL;
blk_dev[ch->major].queue = NULL;
blk_clear(ch->major);
- gd = ch->gd;
+ gd = ch->gd[0];
if (gd) {
- del_gendisk(gd);
+ int i;
+ for (i = 0; i < MAX_DRIVES; i++)
+ del_gendisk(gd + i);
kfree(gd->part);
if (gd->de_arr)
kfree (gd->de_arr);
if (gd->flags)
kfree (gd->flags);
kfree(gd);
- ch->gd = NULL;
+ for (i = 0; i < MAX_DRIVES; i++)
+ ch->gd[i] = NULL;
}
/*
static void channel_init(struct ata_channel *ch)
{
struct gendisk *gd;
+ struct hd_struct *part;
+ devfs_handle_t *de_arr;
+ char *flags;
unsigned int unit;
extern devfs_handle_t ide_devfs_handle;
/* Initialize partition and global device data.
*/
- gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
+ gd = kmalloc (MAX_DRIVES * sizeof(struct gendisk), GFP_KERNEL);
if (!gd)
goto err_kmalloc_gd;
- memset(gd, 0, sizeof(struct gendisk));
+ memset(gd, 0, MAX_DRIVES * sizeof(struct gendisk));
- gd->part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL);
- if (!gd->part)
+ part = kmalloc(ATA_MINORS * sizeof(struct hd_struct), GFP_KERNEL);
+ if (!part)
goto err_kmalloc_gd_part;
- memset(gd->part, 0, ATA_MINORS * sizeof(struct hd_struct));
+ memset(part, 0, ATA_MINORS * sizeof(struct hd_struct));
- gd->de_arr = kmalloc (sizeof(*gd->de_arr) * MAX_DRIVES, GFP_KERNEL);
- if (!gd->de_arr)
+ de_arr = kmalloc (sizeof(devfs_handle_t) * MAX_DRIVES, GFP_KERNEL);
+ if (!de_arr)
goto err_kmalloc_gd_de_arr;
- memset(gd->de_arr, 0, sizeof(*gd->de_arr) * MAX_DRIVES);
+ memset(de_arr, 0, sizeof(devfs_handle_t) * MAX_DRIVES);
- gd->flags = kmalloc (sizeof(*gd->flags) * MAX_DRIVES, GFP_KERNEL);
- if (!gd->flags)
+ flags = kmalloc (sizeof(char) * MAX_DRIVES, GFP_KERNEL);
+ if (!flags)
goto err_kmalloc_gd_flags;
- memset(gd->flags, 0, sizeof(*gd->flags) * MAX_DRIVES);
+ memset(flags, 0, sizeof(char) * MAX_DRIVES);
- for (unit = 0; unit < MAX_DRIVES; ++unit)
- ch->drives[unit].part = &gd->part[unit << PARTN_BITS];
-
- gd->major = ch->major; /* our major device number */
- gd->major_name = IDE_MAJOR_NAME; /* treated special in genhd.c */
- gd->minor_shift = PARTN_BITS; /* num bits for partitions */
- gd->nr_real = MAX_DRIVES; /* current num real drives */
- gd->next = NULL; /* linked list of major devs */
- gd->fops = ide_fops; /* file operations */
-
- ch->gd = gd;
- add_gendisk(gd);
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ gd[unit].part = part + (unit << PARTN_BITS);
+ gd[unit].de_arr = de_arr + unit;
+ gd[unit].flags = flags + unit;
+ ch->drives[unit].part = gd[unit].part;
+ gd[unit].major = ch->major;
+ gd[unit].first_minor = unit << PARTN_BITS;
+ /* treated special in genhd.c */
+ gd[unit].major_name = IDE_MAJOR_NAME;
+ gd[unit].minor_shift = PARTN_BITS;
+ gd[unit].nr_real = 1;
+ gd[unit].fops = ide_fops;
+ ch->gd[unit] = gd + unit;
+ add_gendisk(gd + unit);
+ }
for (unit = 0; unit < MAX_DRIVES; ++unit) {
char name[80];
return;
err_kmalloc_gd_flags:
- kfree(gd->de_arr);
+ kfree(de_arr);
err_kmalloc_gd_de_arr:
- kfree(gd->part);
+ kfree(part);
err_kmalloc_gd_part:
kfree(gd);
err_kmalloc_gd:
static Scsi_Disk ** sd_dsk_arr;
static rwlock_t sd_dsk_arr_lock = RW_LOCK_UNLOCKED;
-static int *sd_max_sectors;
-
static int check_scsidisk_media_change(kdev_t);
static int fop_revalidate_scsidisk(kdev_t);
revalidate: fop_revalidate_scsidisk
};
-/*
- * If we need more than one SCSI disk major (i.e. more than
- * 16 SCSI disks), we'll have to vmalloc() more gendisks later.
- */
-
-static struct gendisk sd_gendisk =
-{
- major: SCSI_DISK0_MAJOR,
- major_name: "sd",
- minor_shift: 4,
- fops: &sd_fops,
-};
-
-static struct gendisk *sd_gendisks = &sd_gendisk;
-
-#define SD_GENDISK(i) sd_gendisks[(i) / SCSI_DISKS_PER_MAJOR]
+static struct gendisk **sd_disks;
/**
* sd_rw_intr - bottom half handler: called when the lower level
sd_dsk_arr[k] = sdkp;
}
}
+ init_mem_lth(sd_disks, sd_template.dev_max);
+ if (sd_disks)
+ zero_mem_lth(sd_disks, sd_template.dev_max);
init_mem_lth(sd, maxparts);
- init_mem_lth(sd_gendisks, N_USED_SD_MAJORS);
- init_mem_lth(sd_max_sectors, sd_template.dev_max << 4);
- if (!sd_dsk_arr || !sd || !sd_gendisks)
+ if (!sd_dsk_arr || !sd || !sd_disks)
goto cleanup_mem;
zero_mem_lth(sd, maxparts);
-
- for (k = 0; k < maxparts; k++) {
- /*
- * Allow lowlevel device drivers to generate 512k large scsi
- * commands if they know what they're doing and they ask for it
- * explicitly via the SHpnt->max_sectors API.
- */
- sd_max_sectors[k] = MAX_PHYS_SEGMENTS*8;
- }
-
- for (k = 0; k < N_USED_SD_MAJORS; k++) {
- int N = SCSI_DISKS_PER_MAJOR;
-
- sd_gendisks[k] = sd_gendisk;
-
- init_mem_lth(sd_gendisks[k].de_arr, N);
- init_mem_lth(sd_gendisks[k].flags, N);
- init_mem_lth(sd_gendisks[k].driverfs_dev_arr, N);
-
- if (!sd_gendisks[k].de_arr || !sd_gendisks[k].flags ||
- !sd_gendisks[k].driverfs_dev_arr)
- goto cleanup_gendisks;
-
- zero_mem_lth(sd_gendisks[k].de_arr, N);
- zero_mem_lth(sd_gendisks[k].flags, N);
- zero_mem_lth(sd_gendisks[k].driverfs_dev_arr, N);
-
- sd_gendisks[k].major = SD_MAJOR(k);
- sd_gendisks[k].major_name = "sd";
- sd_gendisks[k].minor_shift = 4;
- sd_gendisks[k].part = sd + k * (N << 4);
- sd_gendisks[k].nr_real = 0;
- }
return 0;
#undef init_mem_lth
#undef zero_mem_lth
-cleanup_gendisks:
- /* vfree can handle NULL, so no test is required here */
- for (k = 0; k < N_USED_SD_MAJORS; k++) {
- vfree(sd_gendisks[k].de_arr);
- vfree(sd_gendisks[k].flags);
- vfree(sd_gendisks[k].driverfs_dev_arr);
- }
cleanup_mem:
- vfree(sd_gendisks);
- sd_gendisks = NULL;
+ vfree(sd_disks);
+ sd_disks = NULL;
vfree(sd);
sd = NULL;
if (sd_dsk_arr) {
Scsi_Disk * sdkp;
SCSI_LOG_HLQUEUE(3, printk("sd_finish: \n"));
- for (k = 0; k < N_USED_SD_MAJORS; k++) {
+ for (k = 0; k < N_USED_SD_MAJORS; k++)
blk_dev[SD_MAJOR(k)].queue = sd_find_queue;
- add_gendisk(&(sd_gendisks[k]));
- }
for (k = 0; k < sd_template.dev_max; ++k) {
sdkp = sd_get_sdisk(k);
if (sdkp && (0 == sdkp->capacity) && sdkp->device) {
sd_init_onedisk(sdkp, k);
if (!sdkp->has_been_registered) {
- register_disk(&SD_GENDISK(k), MKDEV_SD(k),
+ add_gendisk(sd_disks[k]);
+ register_disk(sd_disks[k], MKDEV_SD(k),
1<<4, &sd_fops,
sdkp->capacity);
sdkp->has_been_registered = 1;
**/
static int sd_attach(Scsi_Device * sdp)
{
- unsigned int devnum;
Scsi_Disk *sdkp;
int dsk_nr;
char diskname[6];
unsigned long iflags;
+ struct {
+ struct gendisk disk;
+ devfs_handle_t de;
+ struct device *dev;
+ char flags;
+ } *p;
+ struct gendisk *gd;
if ((NULL == sdp) ||
((sdp->type != TYPE_DISK) && (sdp->type != TYPE_MOD)))
return 0;
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return 1;
+ gd = &p->disk;
+ gd->de_arr = &p->de;
+ gd->flags = &p->flags;
+ gd->driverfs_dev_arr = &p->dev;
+
SCSI_LOG_HLQUEUE(3, printk("sd_attach: scsi device: <%d,%d,%d,%d>\n",
sdp->host->host_no, sdp->channel, sdp->id, sdp->lun));
if (sd_template.nr_dev >= sd_template.dev_max) {
sdp->attached--;
printk(KERN_ERR "sd_init: no more room for device\n");
+ kfree(p);
return 1;
}
if (dsk_nr >= sd_template.dev_max) {
/* panic("scsi_devices corrupt (sd)"); overkill */
printk(KERN_ERR "sd_init: sd_dsk_arr corrupted\n");
+ kfree(p);
return 1;
}
sd_template.nr_dev++;
- SD_GENDISK(dsk_nr).nr_real++;
- devnum = dsk_nr % SCSI_DISKS_PER_MAJOR;
- SD_GENDISK(dsk_nr).de_arr[devnum] = sdp->de;
- SD_GENDISK(dsk_nr).driverfs_dev_arr[devnum] =
- &sdp->sdev_driverfs_dev;
+ gd->nr_real = 1;
+ gd->de_arr[0] = sdp->de;
+ gd->driverfs_dev_arr[0] = &sdp->sdev_driverfs_dev;
+ gd->major = SD_MAJOR(dsk_nr>>4);
+ gd->first_minor = (dsk_nr & 15)<<4;
+ gd->major_name = "sd";
+ gd->minor_shift = 4;
+ gd->part = sd + (dsk_nr << 4);
+ gd->fops = &sd_fops;
if (sdp->removable)
- SD_GENDISK(dsk_nr).flags[devnum] |= GENHD_FL_REMOVABLE;
+ gd->flags[0] |= GENHD_FL_REMOVABLE;
+ sd_disks[dsk_nr] = gd;
sd_dskname(dsk_nr, diskname);
printk(KERN_NOTICE "Attached scsi %sdisk %s at scsi%d, channel %d, "
"id %d, lun %d\n", sdp->removable ? "removable " : "",
Scsi_Disk *sdkp = NULL;
kdev_t dev;
int dsk_nr;
- int max_p;
- int start;
unsigned long iflags;
SCSI_LOG_HLQUEUE(3, printk("sd_detach: <%d,%d,%d,%d>\n",
for (dsk_nr = 0; dsk_nr < sd_template.dev_max; dsk_nr++) {
sdkp = sd_dsk_arr[dsk_nr];
if (sdkp->device == sdp) {
- sdkp->has_been_registered = 0;
sdkp->device = NULL;
sdkp->capacity = 0;
/* sdkp->detaching = 1; */
if (dsk_nr >= sd_template.dev_max)
return;
- max_p = 1 << sd_gendisk.minor_shift;
- start = dsk_nr << sd_gendisk.minor_shift;
- dev = MKDEV_SD_PARTITION(start);
- driverfs_remove_partitions(&SD_GENDISK (dsk_nr),
- SD_MINOR_NUMBER (start));
- wipe_partitions(dev);
- devfs_register_partitions (&SD_GENDISK (dsk_nr),
- SD_MINOR_NUMBER (start), 1);
- /* unregister_disk() */
+ if (sdkp->has_been_registered) {
+ sdkp->has_been_registered = 0;
+ dev = MKDEV_SD(dsk_nr);
+ driverfs_remove_partitions(sd_disks[dsk_nr], minor(dev));
+ wipe_partitions(dev);
+ devfs_register_partitions (sd_disks[dsk_nr], minor(dev), 1);
+ /* unregister_disk() */
+ del_gendisk(sd_disks[dsk_nr]);
+ }
sdp->attached--;
sd_template.dev_noticed--;
sd_template.nr_dev--;
- SD_GENDISK(dsk_nr).nr_real--;
+ kfree(sd_disks[dsk_nr]);
+ sd_disks[dsk_nr] = NULL;
}
/**
vfree((char *) sd);
for (k = 0; k < N_USED_SD_MAJORS; k++) {
blk_dev[SD_MAJOR(k)].queue = NULL;
- del_gendisk(&(sd_gendisks[k]));
blk_clear(SD_MAJOR(k));
}
sd_template.dev_max = 0;
- if (sd_gendisks != &sd_gendisk)
- vfree(sd_gendisks);
remove_driver(&sd_template.scsi_driverfs_driver);
}
struct pci_dev *pci_dev; /* for pci chipsets */
#endif
struct ata_device drives[MAX_DRIVES]; /* drive info */
- struct gendisk *gd; /* gendisk structure */
+ struct gendisk *gd[MAX_DRIVES]; /* gendisk structure */
/*
* Routines to tune PIO and DMA mode for drives.