bitkeeper revision 1.109 (3e677d37B9PCxHLX7a1Iufrz4eSUqA)

Manual merge of SMH + ACH worlds.
This commit is contained in:
kaf24@labyrinth.cl.cam.ac.uk committed 2003-03-06 16:54:15 +00:00
commit 796305db16
25 files changed
+1535 -977

No files matched your search

+3
View File
@@ -251,6 +251,7 @@
3ddb79be04dyXzyXqDbMRS_1funwXQ xen/drivers/block/blkpg.c
3ddb79beME_0abStePF6fU8XLuQnWw xen/drivers/block/elevator.c
3ddb79beNQVrdGyoI4njXhgAjD6a4A xen/drivers/block/genhd.c
3e677183FxihZVsJDCnvV2S0-FEZyA xen/drivers/block/grok.c
3ddb79beyWwLRP_BiM2t1JKgr_plEw xen/drivers/block/ll_rw_blk.c
3e4a8cb7RhubVgsPwO7cK0pgAN8WCQ xen/drivers/block/xen_block.c
3e5d129asHNyZOjBKTkqs-9AFzxemA xen/drivers/block/xen_segment.c
@@ -477,6 +478,8 @@
3e5a4e65iHEuC5sjFhj42XALYbLVRw xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/Makefile
3e5a4e65pP5spJErBW69pJxSSdK9RA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block.c
3e5a4e65GtI9JZRAjuRdXaxt_4ohyQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_block_test.c
3e677190SjkzJIvFifRVeYpIZOCtYA xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_ide.c
3e677193nOKKTLJzcAu4SYdbZaia8g xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_scsi.c
3e676eb5RXnHzSHgA1BvM0B1aIm4qg xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment.c
3e5d129aDldt6geU2-2SzBae34sQzg xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/block/xl_segment_proc.c
3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ xenolinux-2.4.21-pre4-sparse/arch/xeno/drivers/console/Makefile
+1 -1
View File
@@ -20,7 +20,7 @@ ALL_OBJS += $(BASEDIR)/drivers/pci/driver.o
ALL_OBJS += $(BASEDIR)/drivers/net/driver.o
ALL_OBJS += $(BASEDIR)/drivers/block/driver.o
ALL_OBJS += $(BASEDIR)/drivers/ide/driver.o
#ALL_OBJS += $(BASEDIR)/drivers/scsi/driver.o
ALL_OBJS += $(BASEDIR)/drivers/scsi/driver.o
ALL_OBJS += $(BASEDIR)/arch/$(ARCH)/arch.o
HOSTCC = gcc
+61
View File
@@ -193,6 +193,67 @@ out:
}
#endif
/* XXX SMH: stuff from fs/partitions dumped here temporarily */
/*
* This function will re-read the partition tables for a given device,
* and set things back up again. There are some important caveats,
* however. You must ensure that no one is using the device, and no one
* can start using the device while this function is being executed.
*
* Much of the cleanup from the old partition tables should have already been
* done
*/
void register_disk(struct gendisk *gdev, kdev_t dev, unsigned minors,
struct block_device_operations *ops, long size)
{
if (!gdev)
return;
grok_partitions(gdev, MINOR(dev)>>gdev->minor_shift, minors, size);
}
void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
{
int i;
int first_minor = drive << dev->minor_shift;
int end_minor = first_minor + dev->max_p;
if(!dev->sizes)
blk_size[dev->major] = NULL;
dev->part[first_minor].nr_sects = size;
#ifdef DEVFS_MUST_DIE
/* No such device or no minors to use for partitions */
if ( !size && dev->flags && (dev->flags[drive] & GENHD_FL_REMOVABLE) )
devfs_register_partitions (dev, first_minor, 0);
#endif
if (!size || minors == 1)
return;
if (dev->sizes) {
dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
for (i = first_minor + 1; i < end_minor; i++)
dev->sizes[i] = 0;
}
blk_size[dev->major] = dev->sizes;
#if 0
/* XXX SMH: don't actually check partition details yet */
check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
#endif
/*
* We need to set the sizes array before we will be able to access
* any of the partitions on this device.
*/
if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
for (i = first_minor; i < end_minor; i++)
dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
}
}
extern int blk_dev_init(void);
extern int net_dev_init(void);
+39
View File
@@ -0,0 +1,39 @@
void grok_partitions(struct gendisk *dev, int drive, unsigned minors, long size)
{
int i;
int first_minor = drive << dev->minor_shift;
int end_minor = first_minor + dev->max_p;
if(!dev->sizes)
blk_size[dev->major] = NULL;
dev->part[first_minor].nr_sects = size;
#ifdef DEVFS_MUST_DIE
/* No such device or no minors to use for partitions */
if ( !size && dev->flags && (dev->flags[drive] & GENHD_FL_REMOVABLE) )
devfs_register_partitions (dev, first_minor, 0);
#endif
if (!size || minors == 1)
return;
if (dev->sizes) {
dev->sizes[first_minor] = size >> (BLOCK_SIZE_BITS - 9);
for (i = first_minor + 1; i < end_minor; i++)
dev->sizes[i] = 0;
}
blk_size[dev->major] = dev->sizes;
#if 0
/* XXX SMH: don't actually check partition details yet */
check_partition(dev, MKDEV(dev->major, first_minor), 1 + first_minor);
#endif
/*
* We need to set the sizes array before we will be able to access
* any of the partitions on this device.
*/
if (dev->sizes != NULL) { /* optional safeguard in ll_rw_blk.c */
for (i = first_minor; i < end_minor; i++)
dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
}
}
+59 -57
View File
@@ -240,23 +240,23 @@ static void dispatch_debug_block_io(struct task_struct *p, int index)
static void dispatch_create_segment(struct task_struct *p, int index)
{
blk_ring_t *blk_ring = p->blk_ring_base;
xv_disk_t *xvd;
int result;
blk_ring_t *blk_ring = p->blk_ring_base;
xv_disk_t *xvd;
int result;
if (p->domain != 0)
{
printk (KERN_ALERT "dispatch_create_segment called by dom%d\n", p->domain);
make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_SEG_CREATE, 1);
if (p->domain != 0)
{
DPRINTK("dispatch_create_segment called by dom%d\n", p->domain);
make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_SEG_CREATE, 1);
return;
}
xvd = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);
result = xen_segment_create(xvd);
make_response(p, blk_ring->ring[index].req.id,
XEN_BLOCK_SEG_CREATE, result);
return;
}
xvd = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);
result = xen_segment_create(xvd);
make_response(p, blk_ring->ring[index].req.id,
XEN_BLOCK_SEG_CREATE, result);
return;
}
static void dispatch_delete_segment(struct task_struct *p, int index)
@@ -268,12 +268,16 @@ static void dispatch_probe_blk(struct task_struct *p, int index)
{
extern void ide_probe_devices(xen_disk_info_t *xdi, int *count,
drive_t xdrives[]);
extern void scsi_probe_devices(xen_disk_info_t *xdi, int *count,
drive_t xdrives[]);
blk_ring_t *blk_ring = p->blk_ring_base;
xen_disk_info_t *xdi;
xdi = phys_to_virt((unsigned long)blk_ring->ring[index].req.buffer);
ide_probe_devices(xdi, &num_xdrives, xdrives);
/* scsi_probe_devices(xdi, &num_xdrives, xdrives); */ /* future */
scsi_probe_devices(xdi, &num_xdrives, xdrives);
make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_PROBE_BLK, 0);
}
@@ -371,39 +375,38 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
xen_device = blk_ring->ring[index].req.device;
if (IS_XHD_MAJOR(xen_device))
{
if (xen_device == XHDA_MAJOR) phys_device = MKDEV(IDE0_MAJOR, 0);
else if (xen_device == XHDB_MAJOR) phys_device = MKDEV(IDE1_MAJOR, 0);
else if (xen_device == XHDC_MAJOR) phys_device = MKDEV(IDE2_MAJOR, 0);
else if (xen_device == XHDD_MAJOR) phys_device = MKDEV(IDE3_MAJOR, 0);
else
{
printk (KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
xen_device);
BUG();
}
if (xen_device == XHDA_MAJOR) phys_device = MKDEV(IDE0_MAJOR, 0);
else if (xen_device == XHDB_MAJOR) phys_device = MKDEV(IDE1_MAJOR, 0);
else if (xen_device == XHDC_MAJOR) phys_device = MKDEV(IDE2_MAJOR, 0);
else if (xen_device == XHDD_MAJOR) phys_device = MKDEV(IDE3_MAJOR, 0);
else
{
printk(KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
xen_device);
BUG();
}
block_number = blk_ring->ring[index].req.block_number;
sector_number = blk_ring->ring[index].req.sector_number;
block_number = blk_ring->ring[index].req.block_number;
sector_number = blk_ring->ring[index].req.sector_number;
}
else if (IS_VHD_MAJOR(xen_device))
{
int s;
if (s = xen_segment_map_request(&phys_device, &block_number,
&sector_number,
p, operation, xen_device,
blk_ring->ring[index].req.block_number,
blk_ring->ring[index].req.sector_number))
{
printk ("dispatch_rw_block_io: xen_segment_map_request status: %d\n",
s);
goto bad_descriptor;
}
int s;
if (s = xen_segment_map_request(&phys_device, &block_number,
&sector_number,
p, operation, xen_device,
blk_ring->ring[index].req.block_number,
blk_ring->ring[index].req.sector_number))
{
DPRINTK("dispatch_rw_block_io: xen_seg_map_request status: %d\n", s);
goto bad_descriptor;
}
}
else
{
printk (KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
xen_device);
BUG();
printk (KERN_ALERT "dispatch_rw_block_io: unknown device %d\n",
xen_device);
BUG();
}
bh->b_blocknr = block_number;
@@ -433,9 +436,8 @@ static void dispatch_rw_block_io(struct task_struct *p, int index)
return;
bad_descriptor:
printk (KERN_ALERT "dispatch rw blockio bad descriptor\n");
DPRINTK("dispatch rw blockio bad descriptor\n");
make_response(p, blk_ring->ring[index].req.id, XEN_BLOCK_READ, 1);
return;
}
@@ -468,23 +470,23 @@ static void make_response(struct task_struct *p, void *id,
static void dump_blockq(u_char key, void *dev_id, struct pt_regs *regs)
{
struct task_struct *p;
blk_ring_t *blk_ring ;
struct task_struct *p;
blk_ring_t *blk_ring ;
printk("Dumping block queue stats: nr_pending = %d\n",
atomic_read(&nr_pending));
printk("Dumping block queue stats: nr_pending = %d\n",
atomic_read(&nr_pending));
p = current->next_task;
do
{
printk (KERN_ALERT "Domain: %d\n", p->domain);
blk_ring = p->blk_ring_base;
p = current->next_task;
do
{
printk (KERN_ALERT "Domain: %d\n", p->domain);
blk_ring = p->blk_ring_base;
printk(" req_prod:%d, resp_prod:%d, req_cons:%d\n",
blk_ring->req_prod, blk_ring->resp_prod, p->blk_req_cons);
printk(" req_prod:%d, resp_prod:%d, req_cons:%d\n",
blk_ring->req_prod, blk_ring->resp_prod, p->blk_req_cons);
p = p->next_task;
} while (p != current);
p = p->next_task;
} while (p != current);
}
/* Start-of-day initialisation for a new domain. */
-6
View File
@@ -183,12 +183,6 @@ int unregister_blkdev(unsigned int major, const char * name) { return 0; }
int invalidate_device(kdev_t dev, int do_sync) { return 0; }
/* fs/buffer.c... */
void invalidate_bdev(struct block_device *bdev, int destroy_dirty_buffers) { }
/* fs/partitions/check.c... */
void grok_partitions(struct gendisk *dev, int drive,
unsigned minors, long size) { }
void register_disk(struct gendisk *dev, kdev_t first,
unsigned minors, struct block_device_operations *ops,
long size) { }
/* fs/devices.c... */
const char * kdevname(kdev_t dev) { return NULL; }
/* End of XXXXXX region */
-1
View File
@@ -253,7 +253,6 @@ int aac_get_containers(struct aac_dev *dev)
dinfo->count = cpu_to_le32(index);
dinfo->type = cpu_to_le32(FT_FILESYS);
printk("aac_get_container: getting info for container %d\n", index);
status = fib_send(ContainerCommand,
fibptr,
sizeof (struct aac_query_mount),
+1 -1
View File
@@ -1410,7 +1410,7 @@ unsigned int aac_response_normal(struct aac_queue * q);
unsigned int aac_command_normal(struct aac_queue * q);
#ifdef TRY_TASKLET
extern struct tasklet_struct aac_command_tasklet;
int aac_command_thread(unsigned long data);
void aac_command_thread(unsigned long data);
#else
int aac_command_thread(struct aac_dev * dev);
#endif
+1 -2
View File
@@ -325,10 +325,9 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
}
memset(dev->queues, 0, sizeof(struct aac_queue_block));
printk("aac_init_adapater, dev is %p\n", dev);
if (aac_comm_init(dev)<0)
return NULL;
printk("aac_init_adapater, dev->init is %p\n", dev->init);
/*
* Initialize the list of fibs
*/
+9 -12
View File
@@ -535,12 +535,13 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
* do_softirq() after scheduling the tasklet, as long as we
* are _sure_ we hold no locks here...
*/
printk("about to softirq aac_command_thread...\n");
// printk("about to softirq aac_command_thread...\n");
while (!fibptr->done) {
tasklet_schedule(&aac_command_tasklet);
mdelay(100);
do_softirq(); /* force execution */
// mdelay(100);
}
printk("back from softirq cmd thread and fibptr->done!\n");
// printk("back from softirq cmd thread and fibptr->done!\n");
#else
printk("about to bail at aac_command_thread...\n");
while (!fibptr->done) {
@@ -843,11 +844,12 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
*/
#ifndef TRY_TASKLET
DECLARE_TASKLET_DISABLED(aac_command_tasklet, aac_command_thread, 0);
int aac_command_thread(struct aac_dev * dev)
{
#else
int aac_command_thread(unsigned long data)
DECLARE_TASKLET_DISABLED(aac_command_tasklet, aac_command_thread, 0);
void aac_command_thread(unsigned long data)
#define return(_x) return
{
struct aac_dev *dev = (struct aac_dev *)data;
#endif
@@ -863,9 +865,8 @@ int aac_command_thread(unsigned long data)
/*
* We can only have one thread per adapter for AIF's.
*/
printk("aac_command_'thread': entered.\n");
if (dev->aif_thread)
return -EINVAL;
return(-EINVAL);
#if 0
/*
@@ -888,9 +889,7 @@ int aac_command_thread(unsigned long data)
// while(1)
{
printk("aac_command_thread: in 'loop'\n");
spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags);
printk("flags = %x\n", flags);
while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) {
struct list_head *entry;
struct aac_aifcmd * aifcmd;
@@ -905,7 +904,6 @@ int aac_command_thread(unsigned long data)
spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock,flags);
fib = list_entry(entry, struct hw_fib, header.FibLinks);
printk("aac_command_thread: got fib \n");
/*
* We will process the FIB here or pass it to a
* worker thread that is TBD. We Really can't
@@ -923,7 +921,6 @@ int aac_command_thread(unsigned long data)
*/
aifcmd = (struct aac_aifcmd *) fib->data;
if (aifcmd->command == le16_to_cpu(AifCmdDriverNotify)) {
printk("aac_command_thread: handling aif... :-( \n");
aac_handle_aif(dev, &fibptr);
} else {
/* The u32 here is important and intended. We are using
@@ -1024,5 +1021,5 @@ int aac_command_thread(unsigned long data)
dev->aif_thread = 0;
#endif
return 0;
return(0);
}
+1 -4
View File
@@ -338,7 +338,6 @@ static int aac_detect(Scsi_Host_Template *template)
#endif
template->present = aac_count; /* # of cards of this type found */
printk(KERN_DEBUG "aac_detect: returning %d\n", aac_count);
return aac_count;
}
@@ -461,7 +460,7 @@ static int aac_biosparm(Scsi_Disk *disk, kdev_t dev, int *geom)
struct buffer_head * buf;
dprintk((KERN_DEBUG "aac_biosparm.\n"));
/*
* Assuming extended translation is enabled - #REVISIT#
*/
@@ -499,7 +498,6 @@ static int aac_biosparm(Scsi_Disk *disk, kdev_t dev, int *geom)
* table entry whose end_head matches one of the standard geometry
* translations ( 64/32, 128/32, 255/63 ).
*/
#endif
if(*(unsigned short *)(buf->b_data + 0x1fe) == cpu_to_le16(0xaa55))
@@ -560,7 +558,6 @@ static int aac_biosparm(Scsi_Disk *disk, kdev_t dev, int *geom)
param->heads, param->sectors));
}
}
#if 0
brelse(buf);
#endif
return 0;
+1 -1
View File
@@ -311,7 +311,7 @@ static void aac_rx_start_adapter(struct aac_dev *dev)
struct aac_init *init;
init = dev->init;
printk("aac_rx_start: dev is %p, init is %p\n", dev, init);
init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ);
/*
* Tell the adapter we are back and up and running so it will scan
+468 -480
View File
File diff suppressed because it is too large. Load diff
+141 -138
View File
@@ -633,18 +633,18 @@ struct scsi_device {
* with low level drivers that support multiple outstanding commands.
*/
typedef struct scsi_pointer {
char *ptr; /* data pointer */
int this_residual; /* left in this buffer */
struct scatterlist *buffer; /* which buffer */
int buffers_residual; /* how many buffers left */
dma_addr_t dma_handle;
volatile int Status;
volatile int Message;
volatile int have_data_in;
volatile int sent_command;
volatile int phase;
char *ptr; /* data pointer */
int this_residual; /* left in this buffer */
struct scatterlist *buffer; /* which buffer */
int buffers_residual; /* how many buffers left */
dma_addr_t dma_handle;
volatile int Status;
volatile int Message;
volatile int have_data_in;
volatile int sent_command;
volatile int phase;
} Scsi_Pointer;
/*
@@ -685,146 +685,149 @@ struct scsi_request {
};
/*
* FIXME(eric) - one of the great regrets that I have is that I failed to define
* these structure elements as something like sc_foo instead of foo. This would
* make it so much easier to grep through sources and so forth. I propose that
* all new elements that get added to these structures follow this convention.
* As time goes on and as people have the stomach for it, it should be possible to
* go back and retrofit at least some of the elements here with with the prefix.
*/
* FIXME(eric) - one of the great regrets that I have is that I failed
* to define these structure elements as something like sc_foo instead
* of foo. This would make it so much easier to grep through sources
* and so forth. I propose that all new elements that get added to
* these structures follow this convention. As time goes on and as
* people have the stomach for it, it should be possible to go back
* and retrofit at least some of the elements here with with the
* prefix.
*/
struct scsi_cmnd {
int sc_magic;
int sc_magic;
/* private: */
/*
* This information is private to the scsi mid-layer. Wrapping it in a
* struct private is a way of marking it in a sort of C++ type of way.
*/
struct Scsi_Host *host;
unsigned short state;
unsigned short owner;
Scsi_Device *device;
Scsi_Request *sc_request;
struct scsi_cmnd *next;
struct scsi_cmnd *reset_chain;
int eh_state; /* Used for state tracking in error handlr */
void (*done) (struct scsi_cmnd *); /* Mid-level done function */
/*
A SCSI Command is assigned a nonzero serial_number when internal_cmnd
passes it to the driver's queue command function. The serial_number
is cleared when scsi_done is entered indicating that the command has
been completed. If a timeout occurs, the serial number at the moment
of timeout is copied into serial_number_at_timeout. By subsequently
comparing the serial_number and serial_number_at_timeout fields
during abort or reset processing, we can detect whether the command
has already completed. This also detects cases where the command has
completed and the SCSI Command structure has already being reused
for another command, so that we can avoid incorrectly aborting or
resetting the new command.
*/
unsigned long serial_number;
unsigned long serial_number_at_timeout;
int retries;
int allowed;
int timeout_per_command;
int timeout_total;
int timeout;
/*
* We handle the timeout differently if it happens when a reset,
* abort, etc are in process.
*/
unsigned volatile char internal_timeout;
struct scsi_cmnd *bh_next; /* To enumerate the commands waiting
to be processed. */
/*
* This information is private to the scsi mid-layer. Wrapping it in a
* struct private is a way of marking it in a sort of C++ type of way.
*/
struct Scsi_Host *host;
unsigned short state;
unsigned short owner;
Scsi_Device *device;
Scsi_Request *sc_request;
struct scsi_cmnd *next;
struct scsi_cmnd *reset_chain;
int eh_state; /* Used for state tracking in error handlr */
void (*done) (struct scsi_cmnd *); /* Mid-level done function */
/*
A SCSI Command is assigned a nonzero serial_number when internal_cmnd
passes it to the driver's queue command function. The serial_number
is cleared when scsi_done is entered indicating that the command has
been completed. If a timeout occurs, the serial number at the moment
of timeout is copied into serial_number_at_timeout. By subsequently
comparing the serial_number and serial_number_at_timeout fields
during abort or reset processing, we can detect whether the command
has already completed. This also detects cases where the command has
completed and the SCSI Command structure has already being reused
for another command, so that we can avoid incorrectly aborting or
resetting the new command.
*/
unsigned long serial_number;
unsigned long serial_number_at_timeout;
int retries;
int allowed;
int timeout_per_command;
int timeout_total;
int timeout;
/*
* We handle the timeout differently if it happens when a reset,
* abort, etc are in process.
*/
unsigned volatile char internal_timeout;
struct scsi_cmnd *bh_next; /* To enumerate the commands waiting
to be processed. */
/* public: */
unsigned int target;
unsigned int lun;
unsigned int channel;
unsigned char cmd_len;
unsigned char old_cmd_len;
unsigned char sc_data_direction;
unsigned char sc_old_data_direction;
/* These elements define the operation we are about to perform */
unsigned char cmnd[MAX_COMMAND_SIZE];
unsigned request_bufflen; /* Actual request size */
struct timer_list eh_timeout; /* Used to time out the command. */
void *request_buffer; /* Actual requested buffer */
void **bounce_buffers; /* Array of bounce buffers when using scatter-gather */
/* These elements define the operation we ultimately want to perform */
unsigned char data_cmnd[MAX_COMMAND_SIZE];
unsigned short old_use_sg; /* We save use_sg here when requesting
* sense info */
unsigned short use_sg; /* Number of pieces of scatter-gather */
unsigned short sglist_len; /* size of malloc'd scatter-gather list */
unsigned short abort_reason; /* If the mid-level code requests an
unsigned int target;
unsigned int lun;
unsigned int channel;
unsigned char cmd_len;
unsigned char old_cmd_len;
unsigned char sc_data_direction;
unsigned char sc_old_data_direction;
/* These elements define the operation we are about to perform */
unsigned char cmnd[MAX_COMMAND_SIZE];
unsigned request_bufflen; /* Actual request size */
struct timer_list eh_timeout; /* Used to time out the command. */
void *request_buffer; /* Actual requested buffer */
void **bounce_buffers; /* Array of bounce buffers when
using scatter-gather */
/* These elements define the operation we ultimately want to perform */
unsigned char data_cmnd[MAX_COMMAND_SIZE];
unsigned short old_use_sg; /* We save use_sg here when requesting
* sense info */
unsigned short use_sg; /* Number of pieces of scatter-gather */
unsigned short sglist_len; /* size of malloc'd scatter-gather list */
unsigned short abort_reason; /* If the mid-level code requests an
* abort, this is the reason. */
unsigned bufflen; /* Size of data buffer */
void *buffer; /* Data buffer */
unsigned underflow; /* Return error if less than
this amount is transferred */
unsigned old_underflow; /* save underflow here when reusing the
unsigned bufflen; /* Size of data buffer */
void *buffer; /* Data buffer */
unsigned underflow; /* Return error if less than
this amount is transferred */
unsigned old_underflow; /* save underflow here when reusing the
* command for error handling */
unsigned transfersize; /* How much we are guaranteed to
unsigned transfersize; /* How much we are guaranteed to
transfer with each SCSI transfer
(ie, between disconnect /
reconnects. Probably == sector
size */
int resid; /* Number of bytes requested to be
transferred less actual number
transferred (0 if not supported) */
struct request request; /* A copy of the command we are
int resid; /* Number of bytes requested to be
transferred less actual number
transferred (0 if not supported) */
struct request request; /* A copy of the command we are
working on */
unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
/* obtained by REQUEST SENSE when CHECK CONDITION is
* received on original command (auto-sense) */
unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE]; /* obtained by REQUEST SENSE
* when CHECK CONDITION is
* received on original command
* (auto-sense) */
unsigned flags;
/*
* Used to indicate that a command which has timed out also
* completed normally. Typically the completion function will
* do nothing but set this flag in this instance because the
* timeout handler is already running.
*/
unsigned done_late:1;
/* Low-level done function - can be used by low-level driver to point
* to completion function. Not used by mid/upper level code. */
void (*scsi_done) (struct scsi_cmnd *);
/*
* The following fields can be written to by the host specific code.
* Everything else should be left alone.
*/
Scsi_Pointer SCp; /* Scratchpad used by some host adapters */
unsigned char *host_scribble;
unsigned flags;
/* The host adapter is allowed to call scsi_malloc and get some
* memory and hang it here. The host adapter is also expected to
* call scsi_free to release this memory. (The memory obtained
* by scsi_malloc is guaranteed to be at an address < 16Mb). */
/*
* Used to indicate that a command which has timed out also
* completed normally. Typically the completion function will
* do nothing but set this flag in this instance because the
* timeout handler is already running.
*/
unsigned done_late:1;
/* Low-level done function - can be used by low-level driver to point
* to completion function. Not used by mid/upper level code. */
void (*scsi_done) (struct scsi_cmnd *);
/*
* The following fields can be written to by the host specific code.
* Everything else should be left alone.
*/
Scsi_Pointer SCp; /* Scratchpad used by some host adapters */
unsigned char *host_scribble; /* The host adapter is allowed to
* call scsi_malloc and get some memory
* and hang it here. The host adapter
* is also expected to call scsi_free
* to release this memory. (The memory
* obtained by scsi_malloc is guaranteed
* to be at an address < 16Mb). */
int result; /* Status code from lower level driver */
unsigned char tag; /* SCSI-II queued command tag */
unsigned long pid; /* Process ID, starts at 0 */
int result; /* Status code from lower level driver */
unsigned char tag; /* SCSI-II queued command tag */
unsigned long pid; /* Process ID, starts at 0 */
};
/*
+1 -1
View File
@@ -1914,9 +1914,9 @@ void scsi_error_handler(void *data)
/*
* Wake up the thread that created us.
*/
#if 0
SCSI_LOG_ERROR_RECOVERY(3, printk("Wake up parent %d\n", host->eh_notify->count.counter));
#if 0
up(host->eh_notify);
#endif
+91 -82
View File
@@ -73,7 +73,7 @@ static void __scsi_insert_special(request_queue_t *q, struct request *rq,
unsigned long flags;
ASSERT_LOCK(&io_request_lock, 0);
rq->cmd = SPECIAL;
rq->special = data;
rq->q = NULL;
@@ -362,92 +362,98 @@ static Scsi_Cmnd *__scsi_end_request(Scsi_Cmnd * SCpnt,
int requeue,
int frequeue)
{
struct request *req;
struct buffer_head *bh;
Scsi_Device * SDpnt;
int nsect;
ASSERT_LOCK(&io_request_lock, 0);
req = &SCpnt->request;
req->errors = 0;
if (!uptodate) {
printk(" I/O error: dev %s, sector %lu\n",
kdevname(req->rq_dev), req->sector);
}
do {
if ((bh = req->bh) != NULL) {
nsect = bh->b_size >> 9;
blk_finished_io(nsect);
req->bh = bh->b_reqnext;
bh->b_reqnext = NULL;
sectors -= nsect;
bh->b_end_io(bh, uptodate);
if ((bh = req->bh) != NULL) {
req->hard_sector += nsect;
req->hard_nr_sectors -= nsect;
req->sector += nsect;
req->nr_sectors -= nsect;
req->current_nr_sectors = bh->b_size >> 9;
if (req->nr_sectors < req->current_nr_sectors) {
req->nr_sectors = req->current_nr_sectors;
printk("scsi_end_request: buffer-list destroyed\n");
}
}
struct request *req;
struct buffer_head *bh;
Scsi_Device * SDpnt;
int nsect;
ASSERT_LOCK(&io_request_lock, 0);
req = &SCpnt->request;
req->errors = 0;
if (!uptodate) {
printk(" I/O error: dev %s, sector %lu\n",
kdevname(req->rq_dev), req->sector);
}
do {
if ((bh = req->bh) != NULL) {
nsect = bh->b_size >> 9;
blk_finished_io(nsect);
req->bh = bh->b_reqnext;
bh->b_reqnext = NULL;
sectors -= nsect;
bh->b_end_io(bh, uptodate);
if ((bh = req->bh) != NULL) {
req->hard_sector += nsect;
req->hard_nr_sectors -= nsect;
req->sector += nsect;
req->nr_sectors -= nsect;
req->current_nr_sectors = bh->b_size >> 9;
if (req->nr_sectors < req->current_nr_sectors) {
req->nr_sectors = req->current_nr_sectors;
printk("scsi_end_request: buffer-list destroyed\n");
}
} while (sectors && bh);
}
}
} while (sectors && bh);
/*
* If there are blocks left over at the end, set up the command
* to queue the remainder of them.
*/
if (req->bh) {
request_queue_t *q;
if( !requeue )
{
return SCpnt;
}
q = &SCpnt->device->request_queue;
req->buffer = bh->b_data;
/*
* If there are blocks left over at the end, set up the command
* to queue the remainder of them.
* Bleah. Leftovers again. Stick the leftovers in
* the front of the queue, and goose the queue again.
*/
if (req->bh) {
request_queue_t *q;
if( !requeue )
{
return SCpnt;
}
q = &SCpnt->device->request_queue;
req->buffer = bh->b_data;
/*
* Bleah. Leftovers again. Stick the leftovers in
* the front of the queue, and goose the queue again.
*/
scsi_queue_next_request(q, SCpnt);
return SCpnt;
}
scsi_queue_next_request(q, SCpnt);
return SCpnt;
}
#if 0
/*
* This request is done. If there is someone blocked waiting for this
* request, wake them up. Typically used to wake up processes trying
* to swap a page into memory.
*/
if (req->waiting != NULL) {
complete(req->waiting);
}
/*
* This request is done. If there is someone blocked waiting for this
* request, wake them up. Typically used to wake up processes trying
* to swap a page into memory.
*/
if (req->waiting != NULL) {
complete(req->waiting);
}
#else
/* XXX SMH: we're done -- flip the flag for the spinner :-| */
if(req->waiting && (*(int *)(req->waiting) != NULL)) {
printk("__scsi_end_request: flipping wait status on req %p\n", req);
*(int *)(req->waiting) = NULL;
} // else printk("__scsi_end_request: no-one to notify!!\n");
#endif
req_finished_io(req);
add_blkdev_randomness(MAJOR(req->rq_dev));
SDpnt = SCpnt->device;
/*
* This will goose the queue request function at the end, so we don't
* need to worry about launching another command.
*/
__scsi_release_command(SCpnt);
if( frequeue ) {
request_queue_t *q;
q = &SDpnt->request_queue;
scsi_queue_next_request(q, NULL);
}
return NULL;
req_finished_io(req);
add_blkdev_randomness(MAJOR(req->rq_dev));
SDpnt = SCpnt->device;
/*
* This will goose the queue request function at the end, so we don't
* need to worry about launching another command.
*/
__scsi_release_command(SCpnt);
if( frequeue ) {
request_queue_t *q;
q = &SDpnt->request_queue;
scsi_queue_next_request(q, NULL);
}
return NULL;
}
/*
@@ -554,6 +560,7 @@ void scsi_io_completion(Scsi_Cmnd * SCpnt, int good_sectors,
int this_count = SCpnt->bufflen >> 9;
request_queue_t *q = &SCpnt->device->request_queue;
// printk("scsi_io_completion entered.\n");
/*
* We must do one of several things here:
*
@@ -1053,6 +1060,7 @@ void scsi_request_fn(request_queue_t * q)
* get those allocated here.
*/
if (!SDpnt->scsi_init_io_fn(SCpnt)) {
printk("scsi_request_fn: scsi_init_io_fn failed :-(\n");
SCpnt = __scsi_end_request(SCpnt, 0,
SCpnt->request.nr_sectors, 0, 0);
if( SCpnt != NULL )
@@ -1068,6 +1076,7 @@ void scsi_request_fn(request_queue_t * q)
* Initialize the actual SCSI command for this request.
*/
if (!STpnt->init_command(SCpnt)) {
printk("scsi_request_fn: init_command failed :-(\n");
scsi_release_buffers(SCpnt);
SCpnt = __scsi_end_request(SCpnt, 0,
SCpnt->request.nr_sectors, 0, 0);
+1
View File
@@ -802,6 +802,7 @@ __inline static int __init_io(Scsi_Cmnd * SCpnt,
int this_count;
void ** bbpnt;
// printk("scsi_merge.c: __init_io entered\n");
/*
* FIXME(eric) - don't inline this - it doesn't depend on the
* integer flags. Come to think of it, I don't think this is even
+71 -2
View File
@@ -61,6 +61,8 @@
#include <xeno/genhd.h>
#include <asm/domain_page.h> /* SMH: for [un_]map_domain_mem() */
/*
* static const char RCSid[] = "$Header:";
*/
@@ -324,6 +326,7 @@ static int sd_init_command(Scsi_Cmnd * SCpnt)
!dpnt->device ||
!dpnt->device->online ||
block + SCpnt->request.nr_sectors > ppnt->nr_sects) {
SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n",
SCpnt->request.nr_sectors));
SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt));
@@ -1132,8 +1135,8 @@ static int sd_init()
sd_registered++;
}
/* We do not support attaching loadable devices yet. */
if (rscsi_disks)
return 0;
if (rscsi_disks)
return 0;
rscsi_disks = kmalloc(sd_template.dev_max * sizeof(Scsi_Disk), GFP_ATOMIC);
if (!rscsi_disks)
@@ -1296,9 +1299,73 @@ static void sd_finish()
}
#endif
#if 0
/* XXX SMH: turn on some logging */
scsi_logging_level = ~0;
SCSI_SET_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, 1);
#endif
return;
}
/*
** XXX SMH: gross 'probe' function to allow xeno world to grope us;
** this should really not be in the disk-specific code as it should
** report tapes, CDs, etc. But for now this looks like the easiest
** place to hook it in :-(
*/
void scsi_probe_devices(xen_disk_info_t *xdi)
{
Scsi_Disk *sd;
int i, base, diskinfo[4];
xen_disk_info_t *xen_xdi =
(xen_disk_info_t *)map_domain_mem(virt_to_phys(xdi));
/* We've already had IDE probe => we need to append our info */
base = xen_xdi->count;
for (sd = rscsi_disks, i = 0; i < sd_template.dev_max; i++, sd++) {
if (sd->device !=NULL) {
xen_xdi->disks[xen_xdi->count].type = XEN_DISK_SCSI;
xen_xdi->disks[xen_xdi->count].capacity = sd->capacity;
xen_xdi->count++;
/* default bios params to most commonly used values */
diskinfo[0] = 0x40;
diskinfo[1] = 0x20;
diskinfo[2] = (sd->capacity) >> 11;
/* override with calculated, extended default,
or driver values */
/* XXX SMH: gross in-line literal major number. XXX FIXME. */
if(sd->device->host->hostt->bios_param != NULL)
sd->device->host->hostt->bios_param(
sd, MKDEV(SCSI_DISK0_MAJOR, 0), &diskinfo[0]);
else scsicam_bios_param(sd, MKDEV(SCSI_DISK0_MAJOR, 0),
&diskinfo[0]);
printk (KERN_ALERT "SCSI-XENO %d\n", xen_xdi->count - base);
printk (KERN_ALERT " capacity 0x%x\n", sd->capacity);
printk (KERN_ALERT " head 0x%x\n", diskinfo[0]);
printk (KERN_ALERT " sector 0x%x\n", diskinfo[1]);
printk (KERN_ALERT " cylinder 0x%x\n", diskinfo[2]);
}
}
unmap_domain_mem(xen_xdi);
return;
}
static int sd_detect(Scsi_Device * SDp)
{
if (SDp->type != TYPE_DISK && SDp->type != TYPE_MOD)
@@ -1463,6 +1530,8 @@ static void sd_detach(Scsi_Device * SDp)
static int __init init_sd(void)
{
extern int scsi_register_module(int, void *);
sd_template.module = THIS_MODULE;
return scsi_register_module(MODULE_SCSI_DEV, &sd_template);
}
+1
View File
@@ -32,6 +32,7 @@
#define CONFIG_BLK_DEV_PIIX 1
#define CONFIG_SCSI 1
#define CONFIG_SCSI_LOGGING 1
#define CONFIG_BLK_DEV_SD 1
#define CONFIG_SD_EXTRA_DEVS 40
#define CONFIG_SCSI_MULTI_LUN 1
@@ -1,3 +1,4 @@
O_TARGET := blk.o
obj-y := xl_block.o xl_segment.o xl_segment_proc.o xl_block_test.o
obj-y := xl_block.o xl_ide.o xl_scsi.o xl_segment.o
obj-y += xl_segment_proc.o xl_block_test.o
include $(TOPDIR)/Rules.make
@@ -1,7 +1,7 @@
/******************************************************************************
* xl_block.c
*
* Xenolinux virtual block-device driver (xhd).
* Xenolinux virtual block-device driver.
*
*/
@@ -25,22 +25,23 @@
#include <asm/atomic.h>
#include <asm/uaccess.h>
#define MAJOR_NR XLBLK_MAJOR /* force defns in blk.h, must precede include */
static int xlblk_major = XLBLK_MAJOR;
#include <linux/blk.h>
/* Copied from linux/ide.h */
typedef unsigned char byte;
#define XLBLK_MAX 32 /* Maximum minor devices we support */
#define XLBLK_MAJOR_NAME "xhd"
#define IDE_PARTN_BITS 6 /* from ide.h::PARTN_BITS */
#define IDE_PARTN_MASK ((1<<IDE_PARTN_BITS)-1) /* from ide.h::PARTN_MASK */
static int xlblk_blk_size[XLBLK_MAX];
static int xlblk_blksize_size[XLBLK_MAX];
static int xlblk_read_ahead;
static int xlblk_hardsect_size[XLBLK_MAX];
static int xlblk_max_sectors[XLBLK_MAX];
extern int xlide_init(int xidx, int idx);
extern int xlide_hwsect(int minor);
extern void xlide_cleanup(void);
extern int xlscsi_init(int xidx, int idx);
extern int xlscsi_hwsect(int minor);
extern void xlscsi_cleanup(void);
static int nide = 0; // number of IDE devices we have
static int nscsi = 0; // number of SCSI devices we have
#define XLBLK_MAX 32 /* XXX SMH: this the max of XLIDE_MAX and XLSCSI_MAX */
#define XLBLK_RESPONSE_IRQ _EVENT_BLK_RESP
@@ -56,6 +57,7 @@ static int xlblk_max_sectors[XLBLK_MAX];
static blk_ring_t *blk_ring;
static unsigned int resp_cons; /* Response consumer for comms ring. */
static xen_disk_info_t xlblk_disk_info;
atomic_t xlblk_control_count;
@@ -69,54 +71,139 @@ int hypervisor_request(void * id,
kdev_t device,
struct gendisk *gd);
/* ------------------------------------------------------------------------
*/
static int xenolinux_block_open(struct inode *inode, struct file *filep)
/* Convert from a XenoLinux (major,minor) to the Xen-level 'physical' device */
static kdev_t xldev_to_physdev(kdev_t xldev)
{
int xlmajor = MAJOR(xldev);
int major, minor;
switch(xlmajor) {
case XLIDE_MAJOR:
major = IDE0_MAJOR;
minor = 0; /* we do minor offsetting manually by addition */
break;
case XLSCSI_MAJOR:
major = SCSI_DISK0_MAJOR;
minor = 0; /* we do minor offsetting manually by addition */
break;
default:
panic("xldev_to_physdev: unhandled major %d\n", xlmajor);
break;
}
return MKDEV(major, minor);
}
/*
** Locate the gendisk structure associated with a particular xenolinux disk;
** this requires a scan of the xen_disk_info[] array currently which kind of
** sucks. However we can clean this whole area up later (i.e. post SOSP).
*/
struct gendisk *xldev_to_gendisk(kdev_t xldev, int *t)
{
int i, j, posn, type;
switch(MAJOR(xldev)) {
case XLIDE_MAJOR:
type = 1;
posn = 1;
break;
case XLSCSI_MAJOR:
type = 2;
posn = 1;
break;
default:
panic("xldev_to_gendisk: unhandled major %d\n", MAJOR(xldev));
break;
}
for ( i = j = 0; i < xen_disk_info.count; i++ ) {
if(xen_disk_info.disks[i].type == type)
if(++j == posn)
break;
}
if(t)
*t = type;
return (xen_disk_info.disks[i].gendisk);
}
int xenolinux_block_open(struct inode *inode, struct file *filep)
{
DPRINTK("xenolinux_block_open\n");
return 0;
}
static int xenolinux_block_release(struct inode *inode, struct file *filep)
int xenolinux_block_release(struct inode *inode, struct file *filep)
{
DPRINTK("xenolinux_block_release\n");
return 0;
}
static int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
unsigned command, unsigned long argument)
{
int minor_dev;
int minor_dev, type;
struct hd_geometry *geo = (struct hd_geometry *)argument;
struct gendisk *gd;
struct hd_struct *part;
DPRINTK("xenolinux_block_ioctl\n");
/* check permissions */
if (!capable(CAP_SYS_ADMIN)) return -EPERM;
if (!inode) return -EINVAL;
minor_dev = MINOR(inode->i_rdev);
if (minor_dev >= XLBLK_MAX) return -ENODEV;
DPRINTK_IOCTL("command: 0x%x, argument: 0x%lx, minor: 0x%x\n",
command, (long) argument, minor_dev);
gd = xldev_to_gendisk(inode->i_rdev, &type);
part = &gd->part[minor_dev];
switch (command)
{
case BLKGETSIZE: /* get size */
DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE,
(long) xlblk_disk_info.disks[0].capacity);
return put_user(xlblk_disk_info.disks[0].capacity,
(unsigned long *) argument);
case BLKGETSIZE:
DPRINTK_IOCTL(" BLKGETSIZE: %x %lx\n", BLKGETSIZE, part->nr_sects);
return put_user(part->nr_sects, (unsigned long *) argument);
case BLKRRPART: /* re-read partition table */
DPRINTK_IOCTL(" BLKRRPART: %x\n", BLKRRPART);
break;
case BLKBSZGET: /* get block size */
DPRINTK_IOCTL(" BLKBSZGET: %x\n", BLKBSZGET);
break;
case BLKSSZGET:
switch(type) {
case 1:
DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET,
xlide_hwsect(minor_dev));
return xlide_hwsect(minor_dev);
break;
case 2:
DPRINTK_IOCTL(" BLKSSZGET: %x 0x%x\n", BLKSSZGET,
xlscsi_hwsect(minor_dev));
return xlscsi_hwsect(minor_dev);
break;
default:
printk("BLKSSZGET ioctl() on bogus type %d disk!\n", type);
return 0;
}
case BLKBSZSET: /* set block size */
DPRINTK_IOCTL(" BLKBSZSET: %x\n", BLKBSZSET);
@@ -163,13 +250,13 @@ static int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
return 0;
}
static int xenolinux_block_check(kdev_t dev)
int xenolinux_block_check(kdev_t dev)
{
DPRINTK("xenolinux_block_check\n");
return 0;
}
static int xenolinux_block_revalidate(kdev_t dev)
int xenolinux_block_revalidate(kdev_t dev)
{
DPRINTK("xenolinux_block_revalidate\n");
return 0;
@@ -224,30 +311,13 @@ int hypervisor_request(void * id,
case XEN_BLOCK_READ:
case XEN_BLOCK_WRITE:
/* only accept requests for xhd and vhd devices */
if (!IS_XHD_MAJOR(MAJOR(device)) && !IS_VHD_MAJOR(MAJOR(device)))
panic("error: xl_block::hypervisor_request: "
"unknown device [0x%x]\n", device);
phys_device = MAJOR(device);
/* Compute real buffer location on disk.
* note: gd will be null when we read the partition table.
*/
phys_device = xldev_to_physdev(device);
if (!IS_XHD_MAJOR(MAJOR(device)))
phys_device = MAJOR(device);
/* Compute real buffer location on disk */
sector_number = block_number;
if ( gd != NULL )
{
sector_number += gd->part[MINOR(device)&IDE_PARTN_MASK].start_sect;
}
/*
if (IS_VHD_MAJOR(MAJOR(device)))
{
printk (KERN_ALERT "%lx + %lx = %lx (%x)\n",
block_number,
gd->part[MINOR(device)&IDE_PARTN_MASK].start_sect,
sector_number, device);
}
*/
gd = xldev_to_gendisk(device, NULL);
sector_number += gd->part[MINOR(device)].start_sect;
break;
default:
@@ -274,7 +344,7 @@ int hypervisor_request(void * id,
* do_xlblk_request
* read a block; request is in a request queue
*/
static void do_xlblk_request (request_queue_t *rq)
void do_xlblk_request (request_queue_t *rq)
{
struct request *req;
struct buffer_head *bh;
@@ -282,9 +352,10 @@ static void do_xlblk_request (request_queue_t *rq)
DPRINTK("xlblk.c::do_xlblk_request for '%s'\n", DEVICE_NAME);
while ( !rq->plugged && !QUEUE_EMPTY )
while ( !rq->plugged && !list_empty(&rq->queue_head))
{
if ( (req = CURRENT) == NULL ) goto out;
if ( (req = blkdev_entry_next_request(&rq->queue_head)) == NULL )
goto out;
DPRINTK("do_xlblk_request %p: cmd %i, sec %lx, (%li/%li) bh:%p\n",
req, req->cmd, req->sector,
@@ -351,7 +422,7 @@ static struct block_device_operations xenolinux_block_fops =
static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
{
int i;
int i;
unsigned long flags;
struct buffer_head *bh;
@@ -383,10 +454,18 @@ static void xlblk_response_int(int irq, void *dev_id, struct pt_regs *ptregs)
resp_cons = i;
/* KAF: We can push work down at this point. We have the lock. */
/* aho: okay, so this is a bit of a hack. we'll kick every queue... */
do_xlblk_request(BLK_DEFAULT_QUEUE(XLBLK_MAJOR));
do_xlseg_requestX(BLK_DEFAULT_QUEUE(XLSEG_MAJOR));
for (i = 0; i < xen_disk_info.count; i++) {
/*
** XXX SMH: this is pretty broken ...
** a) should really only kick devs w/ outstanding work
** b) should cover /all/ devs, not just first IDE & SCSI
** KAF will fix this I'm sure.
*/
do_xlblk_request(BLK_DEFAULT_QUEUE(IDE0_MAJOR));
do_xlblk_request(BLK_DEFAULT_QUEUE(SCSI_DISK0_MAJOR));
do_xlseg_requestX(BLK_DEFAULT_QUEUE(XLSEG_MAJOR));
}
spin_unlock_irqrestore(&io_request_lock, flags);
}
@@ -419,143 +498,54 @@ int __init xlblk_init(void)
BUG();
HYPERVISOR_block_io_op();
while ( blk_ring->resp_prod != 1 ) barrier();
printk (KERN_ALERT "xhd block device probe:\n");
for ( i = 0; i < xlblk_disk_info.count; i++ )
{
/*
** SMH: initialize all the disks we found; this is complicated a
** bit by the fact that we have both IDE and SCSI disks underneath
*/
printk (KERN_ALERT " %2d: type: %d, capacity: %ld\n",
i, xlblk_disk_info.disks[i].type,
xlblk_disk_info.disks[i].capacity);
}
SET_MODULE_OWNER(&xenolinux_block_fops);
result = register_blkdev(xlblk_major, "block", &xenolinux_block_fops);
if (result < 0) {
printk (KERN_ALERT "xenolinux block: can't get major %d\n",
xlblk_major);
return result;
switch(xen_disk_info.disks[i].type) {
case 1:
xlide_init(i, nide++);
break;
case 2:
xlscsi_init(i, nscsi++);
break;
default:
printk("Unknown Xen disk type %d\n", xen_disk_info.disks[i].type);
break;
}
}
/* initialize global arrays in drivers/block/ll_rw_block.c */
for (i = 0; i < XLBLK_MAX; i++) {
xlblk_blk_size[i] = xlblk_disk_info.disks[0].capacity;
xlblk_blksize_size[i] = 512;
xlblk_hardsect_size[i] = 512;
xlblk_max_sectors[i] = 128;
}
xlblk_read_ahead = 8;
blk_size[xlblk_major] = xlblk_blk_size;
blksize_size[xlblk_major] = xlblk_blksize_size;
hardsect_size[xlblk_major] = xlblk_hardsect_size;
read_ahead[xlblk_major] = xlblk_read_ahead;
max_sectors[xlblk_major] = xlblk_max_sectors;
blk_init_queue(BLK_DEFAULT_QUEUE(xlblk_major), do_xlblk_request);
/*
* Turn off barking 'headactive' mode. We dequeue buffer heads as
* soon as we pass them down to Xen.
*/
blk_queue_headactive(BLK_DEFAULT_QUEUE(xlblk_major), 0);
xlblk_ide_register_disk(0, xlblk_disk_info.disks[0].capacity);
printk(KERN_ALERT
"XenoLinux Virtual Block Device Driver installed [device: %d]\n",
xlblk_major);
return 0;
fail:
return error;
}
void xlblk_ide_register_disk(int idx, unsigned long capacity)
{
int units;
int minors;
struct gendisk *gd;
/* plagarized from ide-probe.c::init_gendisk */
units = 2; /* from ide.h::MAX_DRIVES */
minors = units * (1<<IDE_PARTN_BITS);
gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
memset(gd->part, 0, minors * sizeof(struct hd_struct));
gd->major = xlblk_major;
gd->major_name = XLBLK_MAJOR_NAME;
gd->minor_shift = IDE_PARTN_BITS;
gd->max_p = 1<<IDE_PARTN_BITS;
gd->nr_real = units;
gd->real_devices = NULL;
gd->next = NULL;
gd->fops = &xenolinux_block_fops;
gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL);
gd->flags = kmalloc (sizeof *gd->flags * units, GFP_KERNEL);
if (gd->de_arr)
memset (gd->de_arr, 0, sizeof *gd->de_arr * units);
if (gd->flags)
memset (gd->flags, 0, sizeof *gd->flags * units);
add_gendisk(gd);
xlblk_disk_info.disks[idx].gendisk = gd;
register_disk(gd, MKDEV(xlblk_major, 0), 1<<IDE_PARTN_BITS,
&xenolinux_block_fops, capacity);
{
int loop = 0;
printk (KERN_ALERT "Partition Table: (capacity: %lx)\n", capacity);
for (loop = 0; loop < minors; loop++)
{
if (gd->part[loop].start_sect && gd->part[loop].nr_sects)
{
printk (KERN_ALERT
" %2d: 0x%6lx %8ld 0x%6lx %7ld\n", loop,
gd->part[loop].start_sect, gd->part[loop].start_sect,
gd->part[loop].nr_sects, gd->part[loop].nr_sects);
}
}
}
return;
}
static void __exit xlblk_cleanup(void)
{
/* CHANGE FOR MULTIQUEUE */
blk_cleanup_queue(BLK_DEFAULT_QUEUE(xlblk_major));
int i;
/* clean up global arrays */
read_ahead[xlblk_major] = 0;
for ( i = 0; i < xen_disk_info.count; i++ )
{
switch(xen_disk_info.disks[i].type) {
case 1:
xlide_cleanup();
break;
case 2:
xlscsi_cleanup();
break;
default:
printk("Unknown Xen disk type %d\n", xen_disk_info.disks[i].type);
break;
}
if (blk_size[xlblk_major])
kfree(blk_size[xlblk_major]);
blk_size[xlblk_major] = NULL;
if (blksize_size[xlblk_major])
kfree(blksize_size[xlblk_major]);
blksize_size[xlblk_major] = NULL;
if (hardsect_size[xlblk_major])
kfree(hardsect_size[xlblk_major]);
hardsect_size[xlblk_major] = NULL;
/* XXX: free each gendisk */
if (unregister_blkdev(xlblk_major, "block"))
printk(KERN_ALERT
"XenoLinux Virtual Block Device Driver uninstalled w/ errs\n");
else
printk(KERN_ALERT
"XenoLinux Virtual Block Device Driver uninstalled\n");
}
return;
}
@@ -0,0 +1,200 @@
/******************************************************************************
* xl_ide.c
*
* Xenolinux virtual IDE block-device driver.
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/hdreg.h>
#include <linux/blkdev.h>
#include <linux/major.h>
#define MAJOR_NR XLIDE_MAJOR /* force defns in blk.h, must precede include */
static int xlide_major = XLIDE_MAJOR;
#include <linux/blk.h>
void xlide_ide_register_disk(int, unsigned long);
#define XLIDE_MAX 32 /* Maximum minor devices we support */
#define XLIDE_MAJOR_NAME "xhd"
#define IDE_PARTN_BITS 6 /* from ide.h::PARTN_BITS */
#define IDE_PARTN_MASK ((1<<IDE_PARTN_BITS)-1) /* from ide.h::PARTN_MASK */
static int xlide_blk_size[XLIDE_MAX];
static int xlide_blksize_size[XLIDE_MAX];
static int xlide_read_ahead;
static int xlide_hardsect_size[XLIDE_MAX];
static int xlide_max_sectors[XLIDE_MAX];
extern xen_disk_info_t xen_disk_info;
extern int xenolinux_block_open(struct inode *inode, struct file *filep);
extern int xenolinux_block_release(struct inode *inode, struct file *filep);
extern int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
unsigned command, unsigned long argument);
extern int xenolinux_block_check(kdev_t dev);
extern int xenolinux_block_revalidate(kdev_t dev);
extern void do_xlblk_request (request_queue_t *rq);
static struct block_device_operations xlide_block_fops =
{
open: xenolinux_block_open,
release: xenolinux_block_release,
ioctl: xenolinux_block_ioctl,
check_media_change: xenolinux_block_check,
revalidate: xenolinux_block_revalidate,
};
/* tiny inteface fn */
int xlide_hwsect(int minor)
{
return xlide_hardsect_size[minor];
}
void xlide_register_disk(int xidx, int idx)
{
int units;
int minors;
struct gendisk *gd;
/* plagarized from ide-probe.c::init_gendisk */
units = 2; /* from ide.h::MAX_DRIVES */
minors = units * (1<<IDE_PARTN_BITS);
gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
memset(gd->part, 0, minors * sizeof(struct hd_struct));
gd->major = xlide_major; /* XXX should be idx-specific */
gd->major_name = XLIDE_MAJOR_NAME; /* XXX should be idx-specific */
gd->minor_shift = IDE_PARTN_BITS;
gd->max_p = 1<<IDE_PARTN_BITS;
gd->nr_real = units;
gd->real_devices = NULL;
gd->next = NULL;
gd->fops = &xlide_block_fops;
gd->de_arr = kmalloc (sizeof *gd->de_arr * units, GFP_KERNEL);
gd->flags = kmalloc (sizeof *gd->flags * units, GFP_KERNEL);
if (gd->de_arr)
memset (gd->de_arr, 0, sizeof *gd->de_arr * units);
if (gd->flags)
memset (gd->flags, 0, sizeof *gd->flags * units);
add_gendisk(gd);
xen_disk_info.disks[xidx].gendisk = gd;
/* XXX major should be idx-specific */
register_disk(gd, MKDEV(xlide_major, 0), 1<<IDE_PARTN_BITS,
&xlide_block_fops, xen_disk_info.disks[xidx].capacity);
return;
}
/*
** Initialize a XenoLinux IDE disk; the 'xidx' is the index into the
** xen_disk_info array so we can grab interesting values; the 'idx' is
** a count of the number of XLSCSI disks we've seen so far, starting at 0
** XXX SMH: this is all so ugly because the xen_disk_info() structure and
** array doesn't really give us what we want. Ho hum. To be tidied someday.
*/
int xlide_init(int xidx, int idx)
{
int i, major, result;
SET_MODULE_OWNER(&xlide_block_fops);
major = xlide_major + idx; /* XXX assume we have a linear major space */
/* XXX SMH: name below should vary with major */
result = register_blkdev(major, XLIDE_MAJOR_NAME, &xlide_block_fops);
if (result < 0) {
printk (KERN_ALERT "XL IDE: can't get major %d\n",
major);
return result;
}
/* initialize global arrays in drivers/block/ll_rw_block.c */
for (i = 0; i < XLIDE_MAX; i++) {
xlide_blk_size[i] = xen_disk_info.disks[0].capacity;
xlide_blksize_size[i] = 512;
xlide_hardsect_size[i] = 512;
xlide_max_sectors[i] = 128;
}
xlide_read_ahead = 8;
blk_size[major] = xlide_blk_size;
blksize_size[major] = xlide_blksize_size;
hardsect_size[major] = xlide_hardsect_size;
read_ahead[major] = xlide_read_ahead;
max_sectors[major] = xlide_max_sectors;
blk_init_queue(BLK_DEFAULT_QUEUE(major), do_xlblk_request);
/*
* Turn off barking 'headactive' mode. We dequeue buffer heads as
* soon as we pass them down to Xen.
*/
blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0);
xlide_register_disk(xidx, idx);
printk(KERN_ALERT
"XenoLinux Virtual IDE Device Driver installed [device: %d]\n",
major);
return 0;
}
void xlide_cleanup(void)
{
/* CHANGE FOR MULTIQUEUE */
blk_cleanup_queue(BLK_DEFAULT_QUEUE(xlide_major));
/* clean up global arrays */
read_ahead[xlide_major] = 0;
if (blk_size[xlide_major])
kfree(blk_size[xlide_major]);
blk_size[xlide_major] = NULL;
if (blksize_size[xlide_major])
kfree(blksize_size[xlide_major]);
blksize_size[xlide_major] = NULL;
if (hardsect_size[xlide_major])
kfree(hardsect_size[xlide_major]);
hardsect_size[xlide_major] = NULL;
/* XXX: free each gendisk */
if (unregister_blkdev(xlide_major, XLIDE_MAJOR_NAME))
printk(KERN_ALERT
"XenoLinux Virtual IDE Device Driver uninstalled w/ errs\n");
else
printk(KERN_ALERT
"XenoLinux Virtual IDE Device Driver uninstalled\n");
return;
}
@@ -0,0 +1,211 @@
/******************************************************************************
* xl_scsi.c
*
* Xenolinux virtual SCSI block-device driver.
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/hdreg.h>
#include <linux/blkdev.h>
#include <linux/major.h>
#define MAJOR_NR XLSCSI_MAJOR /* force defns in blk.h, must precede include */
static int xlscsi_major = XLSCSI_MAJOR;
#include <linux/blk.h>
/* Copied from linux/ide.h */
typedef unsigned char byte;
void xlscsi_ide_register_disk(int, unsigned long);
#define SCSI_DISKS_PER_MAJOR 16 /* max number of devices per scsi major */
#define XLSCSI_MAX 32 /* maximum minor devices we support */
#define XLSCSI_MAJOR_NAME "xsd"
static int xlscsi_blk_size[XLSCSI_MAX];
static int xlscsi_blksize_size[XLSCSI_MAX];
static int xlscsi_read_ahead;
static int xlscsi_hardsect_size[XLSCSI_MAX];
static int xlscsi_max_sectors[XLSCSI_MAX];
#if 0
#define DPRINTK(_f, _a...) printk ( KERN_ALERT _f , ## _a )
#define DPRINTK_IOCTL(_f, _a...) printk ( KERN_ALERT _f , ## _a )
#else
#define DPRINTK(_f, _a...) ((void)0)
#define DPRINTK_IOCTL(_f, _a...) ((void)0)
#endif
extern xen_disk_info_t xen_disk_info;
extern int xenolinux_block_open(struct inode *inode, struct file *filep);
extern int xenolinux_block_release(struct inode *inode, struct file *filep);
extern int xenolinux_block_ioctl(struct inode *inode, struct file *filep,
unsigned command, unsigned long argument);
extern int xenolinux_block_check(kdev_t dev);
extern int xenolinux_block_revalidate(kdev_t dev);
extern void do_xlblk_request (request_queue_t *rq);
static struct block_device_operations xlscsi_block_fops =
{
open: xenolinux_block_open,
release: xenolinux_block_release,
ioctl: xenolinux_block_ioctl,
check_media_change: xenolinux_block_check,
revalidate: xenolinux_block_revalidate,
};
/* tiny inteface fn */
int xlscsi_hwsect(int minor)
{
return xlscsi_hardsect_size[minor];
}
void xlscsi_register_disk(int xidx, int idx)
{
int minors;
struct gendisk *gd;
unsigned long capacity;
minors = XLSCSI_MAX;
gd = kmalloc (sizeof(struct gendisk), GFP_KERNEL);
gd->sizes = kmalloc (minors * sizeof(int), GFP_KERNEL);
gd->part = kmalloc (minors * sizeof(struct hd_struct), GFP_KERNEL);
memset(gd->part, 0, minors * sizeof(struct hd_struct));
if(idx > 0)
printk("xlscsi_register_disk: need fix to handle "
"multiple SCSI majors!\n");
gd->major = xlscsi_major; /* XXX should be idx-specific */
gd->major_name = XLSCSI_MAJOR_NAME; /* XXX should be idx-specific */
gd->minor_shift = 4;
gd->max_p = 1<<4;
gd->nr_real = SCSI_DISKS_PER_MAJOR;
gd->real_devices = NULL;
gd->next = NULL;
gd->fops = &xlscsi_block_fops;
gd->de_arr = kmalloc (sizeof *gd->de_arr * SCSI_DISKS_PER_MAJOR,
GFP_KERNEL);
gd->flags = kmalloc (sizeof *gd->flags * SCSI_DISKS_PER_MAJOR,
GFP_KERNEL);
if (gd->de_arr)
memset (gd->de_arr, 0, sizeof *gd->de_arr * SCSI_DISKS_PER_MAJOR);
if (gd->flags)
memset (gd->flags, 0, sizeof *gd->flags * SCSI_DISKS_PER_MAJOR);
add_gendisk(gd);
xen_disk_info.disks[xidx].gendisk = gd;
/* XXX major below should be idx-specific */
register_disk(gd, MKDEV(xlscsi_major, 0), 1<<4, &xlscsi_block_fops,
xen_disk_info.disks[xidx].capacity);
return;
}
/*
** Initialize a XenoLinux SCSI disk; the 'xidx' is the index into the
** xen_disk_info array so we can grab interesting values; the 'idx' is
** a count of the number of XLSCSI disks we've seen so far, starting at 0
** XXX SMH: this is all so ugly because the xen_disk_info() structure and
** array doesn't really give us what we want. Ho hum. To be tidied someday.
*/
int xlscsi_init(int xidx, int idx)
{
int i, major, result;
SET_MODULE_OWNER(&xlscsi_block_fops);
major = xlscsi_major + idx; /* XXX asume we have linear major space */
/* XXX SMH: 'name' below should vary for different major values */
result = register_blkdev(major, XLSCSI_MAJOR_NAME, &xlscsi_block_fops);
if (result < 0) {
printk (KERN_ALERT "XL SCSI: can't get major %d\n", major);
return result;
}
/* initialize global arrays in drivers/block/ll_rw_block.c */
for (i = 0; i < XLSCSI_MAX; i++) {
xlscsi_blk_size[i] = xen_disk_info.disks[xidx].capacity;
xlscsi_blksize_size[i] = 512;
xlscsi_hardsect_size[i] = 512;
xlscsi_max_sectors[i] = 128;
}
xlscsi_read_ahead = 8;
blk_size[major] = xlscsi_blk_size;
blksize_size[major] = xlscsi_blksize_size;
hardsect_size[major] = xlscsi_hardsect_size;
read_ahead[major] = xlscsi_read_ahead;
max_sectors[major] = xlscsi_max_sectors;
blk_init_queue(BLK_DEFAULT_QUEUE(major), do_xlblk_request);
/*
* Turn off barking 'headactive' mode. We dequeue buffer heads as
* soon as we pass them down to Xen.
*/
blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0);
xlscsi_register_disk(xidx, idx);
printk(KERN_ALERT
"XenoLinux Virtual SCSI Device Driver installed [device: %d]\n",
major);
return 0;
}
void xlscsi_cleanup(void)
{
/* CHANGE FOR MULTIQUEUE */
blk_cleanup_queue(BLK_DEFAULT_QUEUE(xlscsi_major));
/* clean up global arrays */
read_ahead[xlscsi_major] = 0;
if (blk_size[xlscsi_major])
kfree(blk_size[xlscsi_major]);
blk_size[xlscsi_major] = NULL;
if (blksize_size[xlscsi_major])
kfree(blksize_size[xlscsi_major]);
blksize_size[xlscsi_major] = NULL;
if (hardsect_size[xlscsi_major])
kfree(hardsect_size[xlscsi_major]);
hardsect_size[xlscsi_major] = NULL;
/* XXX: free each gendisk */
if (unregister_blkdev(xlscsi_major, XLSCSI_MAJOR_NAME))
printk(KERN_ALERT
"XenoLinux Virtual SCSI Device Driver uninstalled w/ errs\n");
else
printk(KERN_ALERT
"XenoLinux Virtual SCSI Device Driver uninstalled\n");
return;
}
@@ -145,8 +145,8 @@
#define UMEM_MAJOR 116 /* http://www.umem.com/ Battery Backed RAM */
/* note: 123, 124, 125, 126 and 234, 235, 236, 237 are defined in xeno_major */
#include <asm/hypervisor-ifs/xeno-major.h>
#define XLIDE_MAJOR 123 /* XenoLinux IDE Device */
#define XLSCSI_MAJOR 133 /* XenoLinux SCSI Device */
#define RTF_MAJOR 150
#define RAW_MAJOR 162
@@ -232,13 +232,7 @@ static struct dev_name_struct {
{ "ataraid/d15p",0x72F0 },
#if defined(CONFIG_XENOLINUX_BLOCK)
{ "xhda", 0x7B00 },
{ "xhdb", 0x7C00 },
{ "xhdc", 0x7D00 },
{ "xhdd", 0x7E00 },
{ "vhda", 0xEA00 },
{ "vhdb", 0xEB00 },
{ "vhdc", 0xEC00 },
{ "vhdd", 0xED00 },
{ "xsda", 0x8500 },
#endif
{ "nftla", 0x5d00 },
{ "nftlb", 0x5d10 },
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.