diff options
| author | Markus Lidel <Markus.Lidel@shadowconnect.com> | 2005-06-24 01:02:19 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-24 03:05:28 -0400 |
| commit | b2aaee33fbb354a2f08121aa1c1be55841102761 (patch) | |
| tree | 7567ca61aaf5eed8bb1acd01cd87aa235b854fd4 | |
| parent | f10378fff658f61307496e0ae00095041725cf07 (diff) | |
[PATCH] I2O: Adaptec specific SG_IO access, firmware access through sysfs and 2400A workaround
Changes:
- Provide SG_IO access to BLOCK and EXECUTIVE class on Adaptec
controllers
- Use PRIVATE messages in SCSI-OSM because on some controllers normal
SCSI class commands like READ or READ CAPACITY cause errors
- Use new DMA and SG list creation function
- Added workaround to limit sectors per request for Adaptec 2400A
controllers
Signed-off-by: Markus Lidel <Markus.Lidel@shadowconnect.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | drivers/message/i2o/Kconfig | 18 | ||||
| -rw-r--r-- | drivers/message/i2o/i2o_block.h | 6 | ||||
| -rw-r--r-- | drivers/message/i2o/i2o_config.c | 4 | ||||
| -rw-r--r-- | drivers/message/i2o/i2o_scsi.c | 263 | ||||
| -rw-r--r-- | drivers/message/i2o/pci.c | 22 | ||||
| -rw-r--r-- | include/linux/i2o-dev.h | 22 | ||||
| -rw-r--r-- | include/linux/i2o.h | 37 | ||||
| -rw-r--r-- | include/scsi/sg_request.h | 26 |
8 files changed, 282 insertions, 116 deletions
diff --git a/drivers/message/i2o/Kconfig b/drivers/message/i2o/Kconfig index ce278e060a..94b6d676c5 100644 --- a/drivers/message/i2o/Kconfig +++ b/drivers/message/i2o/Kconfig | |||
| @@ -24,6 +24,24 @@ config I2O | |||
| 24 | 24 | ||
| 25 | If unsure, say N. | 25 | If unsure, say N. |
| 26 | 26 | ||
| 27 | config I2O_EXT_ADAPTEC | ||
| 28 | bool "Enable Adaptec extensions" | ||
| 29 | depends on I2O | ||
| 30 | default y | ||
| 31 | ---help--- | ||
| 32 | Say Y for support of raidutils for Adaptec I2O controllers. You also | ||
| 33 | have to say Y to "I2O Configuration support", "I2O SCSI OSM" below | ||
| 34 | and to "SCSI generic support" under "SCSI device configuration". | ||
| 35 | |||
| 36 | config I2O_EXT_ADAPTEC_DMA64 | ||
| 37 | bool "Enable 64-bit DMA" | ||
| 38 | depends on I2O_EXT_ADAPTEC && ( 64BIT || HIGHMEM64G ) | ||
| 39 | default y | ||
| 40 | ---help--- | ||
| 41 | Say Y for support of 64-bit DMA transfer mode on Adaptec I2O | ||
| 42 | controllers. | ||
| 43 | Note: You need at least firmware version 3709. | ||
| 44 | |||
| 27 | config I2O_CONFIG | 45 | config I2O_CONFIG |
| 28 | tristate "I2O Configuration support" | 46 | tristate "I2O Configuration support" |
| 29 | depends on PCI && I2O | 47 | depends on PCI && I2O |
diff --git a/drivers/message/i2o/i2o_block.h b/drivers/message/i2o/i2o_block.h index 9e1a95fb08..e45cc40ce3 100644 --- a/drivers/message/i2o/i2o_block.h +++ b/drivers/message/i2o/i2o_block.h | |||
| @@ -56,6 +56,12 @@ | |||
| 56 | #define I2O_BLOCK_RETRY_TIME HZ/4 | 56 | #define I2O_BLOCK_RETRY_TIME HZ/4 |
| 57 | #define I2O_BLOCK_MAX_OPEN_REQUESTS 50 | 57 | #define I2O_BLOCK_MAX_OPEN_REQUESTS 50 |
| 58 | 58 | ||
| 59 | /* request queue sizes */ | ||
| 60 | #define I2O_BLOCK_REQ_MEMPOOL_SIZE 32 | ||
| 61 | |||
| 62 | #define KERNEL_SECTOR_SHIFT 9 | ||
| 63 | #define KERNEL_SECTOR_SIZE (1 << KERNEL_SECTOR_SHIFT) | ||
| 64 | |||
| 59 | /* I2O Block OSM mempool struct */ | 65 | /* I2O Block OSM mempool struct */ |
| 60 | struct i2o_block_mempool { | 66 | struct i2o_block_mempool { |
| 61 | kmem_cache_t *slab; | 67 | kmem_cache_t *slab; |
diff --git a/drivers/message/i2o/i2o_config.c b/drivers/message/i2o/i2o_config.c index 849d90aad7..7636833b46 100644 --- a/drivers/message/i2o/i2o_config.c +++ b/drivers/message/i2o/i2o_config.c | |||
| @@ -515,6 +515,7 @@ static int i2o_cfg_evt_get(unsigned long arg, struct file *fp) | |||
| 515 | return 0; | 515 | return 0; |
| 516 | } | 516 | } |
| 517 | 517 | ||
| 518 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 518 | #ifdef CONFIG_COMPAT | 519 | #ifdef CONFIG_COMPAT |
| 519 | static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long arg) | 520 | static int i2o_cfg_passthru32(struct file *file, unsigned cmnd, unsigned long arg) |
| 520 | { | 521 | { |
| @@ -964,6 +965,7 @@ static int i2o_cfg_passthru(unsigned long arg) | |||
| 964 | kfree(reply); | 965 | kfree(reply); |
| 965 | return rcode; | 966 | return rcode; |
| 966 | } | 967 | } |
| 968 | #endif | ||
| 967 | 969 | ||
| 968 | /* | 970 | /* |
| 969 | * IOCTL Handler | 971 | * IOCTL Handler |
| @@ -1018,9 +1020,11 @@ static int i2o_cfg_ioctl(struct inode *inode, struct file *fp, unsigned int cmd, | |||
| 1018 | ret = i2o_cfg_evt_get(arg, fp); | 1020 | ret = i2o_cfg_evt_get(arg, fp); |
| 1019 | break; | 1021 | break; |
| 1020 | 1022 | ||
| 1023 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 1021 | case I2OPASSTHRU: | 1024 | case I2OPASSTHRU: |
| 1022 | ret = i2o_cfg_passthru(arg); | 1025 | ret = i2o_cfg_passthru(arg); |
| 1023 | break; | 1026 | break; |
| 1027 | #endif | ||
| 1024 | 1028 | ||
| 1025 | default: | 1029 | default: |
| 1026 | osm_debug("unknown ioctl called!\n"); | 1030 | osm_debug("unknown ioctl called!\n"); |
diff --git a/drivers/message/i2o/i2o_scsi.c b/drivers/message/i2o/i2o_scsi.c index c3b0c29ac0..fef53b509a 100644 --- a/drivers/message/i2o/i2o_scsi.c +++ b/drivers/message/i2o/i2o_scsi.c | |||
| @@ -55,6 +55,7 @@ | |||
| 55 | #include <linux/pci.h> | 55 | #include <linux/pci.h> |
| 56 | #include <linux/blkdev.h> | 56 | #include <linux/blkdev.h> |
| 57 | #include <linux/i2o.h> | 57 | #include <linux/i2o.h> |
| 58 | #include <linux/scatterlist.h> | ||
| 58 | 59 | ||
| 59 | #include <asm/dma.h> | 60 | #include <asm/dma.h> |
| 60 | #include <asm/system.h> | 61 | #include <asm/system.h> |
| @@ -65,19 +66,23 @@ | |||
| 65 | #include <scsi/scsi_host.h> | 66 | #include <scsi/scsi_host.h> |
| 66 | #include <scsi/scsi_device.h> | 67 | #include <scsi/scsi_device.h> |
| 67 | #include <scsi/scsi_cmnd.h> | 68 | #include <scsi/scsi_cmnd.h> |
| 69 | #include <scsi/scsi_request.h> | ||
| 70 | #include <scsi/sg.h> | ||
| 71 | #include <scsi/sg_request.h> | ||
| 68 | 72 | ||
| 69 | #define OSM_NAME "scsi-osm" | 73 | #define OSM_NAME "scsi-osm" |
| 70 | #define OSM_VERSION "$Rev$" | 74 | #define OSM_VERSION "1.282" |
| 71 | #define OSM_DESCRIPTION "I2O SCSI Peripheral OSM" | 75 | #define OSM_DESCRIPTION "I2O SCSI Peripheral OSM" |
| 72 | 76 | ||
| 73 | static struct i2o_driver i2o_scsi_driver; | 77 | static struct i2o_driver i2o_scsi_driver; |
| 74 | 78 | ||
| 75 | static int i2o_scsi_max_id = 16; | 79 | static unsigned int i2o_scsi_max_id = 16; |
| 76 | static int i2o_scsi_max_lun = 8; | 80 | static unsigned int i2o_scsi_max_lun = 255; |
| 77 | 81 | ||
| 78 | struct i2o_scsi_host { | 82 | struct i2o_scsi_host { |
| 79 | struct Scsi_Host *scsi_host; /* pointer to the SCSI host */ | 83 | struct Scsi_Host *scsi_host; /* pointer to the SCSI host */ |
| 80 | struct i2o_controller *iop; /* pointer to the I2O controller */ | 84 | struct i2o_controller *iop; /* pointer to the I2O controller */ |
| 85 | unsigned int lun; /* lun's used for block devices */ | ||
| 81 | struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */ | 86 | struct i2o_device *channel[0]; /* channel->i2o_dev mapping table */ |
| 82 | }; | 87 | }; |
| 83 | 88 | ||
| @@ -100,12 +105,17 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) | |||
| 100 | u8 type; | 105 | u8 type; |
| 101 | int i; | 106 | int i; |
| 102 | size_t size; | 107 | size_t size; |
| 103 | i2o_status_block *sb; | 108 | u16 body_size = 6; |
| 109 | |||
| 110 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 111 | if (c->adaptec) | ||
| 112 | body_size = 8; | ||
| 113 | #endif | ||
| 104 | 114 | ||
| 105 | list_for_each_entry(i2o_dev, &c->devices, list) | 115 | list_for_each_entry(i2o_dev, &c->devices, list) |
| 106 | if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { | 116 | if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { |
| 107 | if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) | 117 | if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) |
| 108 | && (type == 0x01)) /* SCSI bus */ | 118 | && (type == 0x01)) /* SCSI bus */ |
| 109 | max_channel++; | 119 | max_channel++; |
| 110 | } | 120 | } |
| 111 | 121 | ||
| @@ -127,20 +137,18 @@ static struct i2o_scsi_host *i2o_scsi_host_alloc(struct i2o_controller *c) | |||
| 127 | scsi_host->max_id = i2o_scsi_max_id; | 137 | scsi_host->max_id = i2o_scsi_max_id; |
| 128 | scsi_host->max_lun = i2o_scsi_max_lun; | 138 | scsi_host->max_lun = i2o_scsi_max_lun; |
| 129 | scsi_host->this_id = c->unit; | 139 | scsi_host->this_id = c->unit; |
| 130 | 140 | scsi_host->sg_tablesize = i2o_sg_tablesize(c, body_size); | |
| 131 | sb = c->status_block.virt; | ||
| 132 | |||
| 133 | scsi_host->sg_tablesize = (sb->inbound_frame_size - | ||
| 134 | sizeof(struct i2o_message) / 4 - 6) / 2; | ||
| 135 | 141 | ||
| 136 | i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata; | 142 | i2o_shost = (struct i2o_scsi_host *)scsi_host->hostdata; |
| 137 | i2o_shost->scsi_host = scsi_host; | 143 | i2o_shost->scsi_host = scsi_host; |
| 138 | i2o_shost->iop = c; | 144 | i2o_shost->iop = c; |
| 145 | i2o_shost->lun = 1; | ||
| 139 | 146 | ||
| 140 | i = 0; | 147 | i = 0; |
| 141 | list_for_each_entry(i2o_dev, &c->devices, list) | 148 | list_for_each_entry(i2o_dev, &c->devices, list) |
| 142 | if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { | 149 | if (i2o_dev->lct_data.class_id == I2O_CLASS_BUS_ADAPTER) { |
| 143 | if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) || (type == 1)) /* only SCSI bus */ | 150 | if (i2o_parm_field_get(i2o_dev, 0x0000, 0, &type, 1) |
| 151 | && (type == 0x01)) /* only SCSI bus */ | ||
| 144 | i2o_shost->channel[i++] = i2o_dev; | 152 | i2o_shost->channel[i++] = i2o_dev; |
| 145 | 153 | ||
| 146 | if (i >= max_channel) | 154 | if (i >= max_channel) |
| @@ -212,8 +220,8 @@ static int i2o_scsi_probe(struct device *dev) | |||
| 212 | struct Scsi_Host *scsi_host; | 220 | struct Scsi_Host *scsi_host; |
| 213 | struct i2o_device *parent; | 221 | struct i2o_device *parent; |
| 214 | struct scsi_device *scsi_dev; | 222 | struct scsi_device *scsi_dev; |
| 215 | u32 id; | 223 | u32 id = -1; |
| 216 | u64 lun; | 224 | u64 lun = -1; |
| 217 | int channel = -1; | 225 | int channel = -1; |
| 218 | int i; | 226 | int i; |
| 219 | 227 | ||
| @@ -223,8 +231,56 @@ static int i2o_scsi_probe(struct device *dev) | |||
| 223 | 231 | ||
| 224 | scsi_host = i2o_shost->scsi_host; | 232 | scsi_host = i2o_shost->scsi_host; |
| 225 | 233 | ||
| 226 | if (i2o_parm_field_get(i2o_dev, 0, 3, &id, 4) < 0) | 234 | switch (i2o_dev->lct_data.class_id) { |
| 235 | case I2O_CLASS_RANDOM_BLOCK_STORAGE: | ||
| 236 | case I2O_CLASS_EXECUTIVE: | ||
| 237 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 238 | if (c->adaptec) { | ||
| 239 | u8 type; | ||
| 240 | struct i2o_device *d = i2o_shost->channel[0]; | ||
| 241 | |||
| 242 | if (i2o_parm_field_get(d, 0x0000, 0, &type, 1) | ||
| 243 | && (type == 0x01)) /* SCSI bus */ | ||
| 244 | if (i2o_parm_field_get(d, 0x0200, 4, &id, 4)) { | ||
| 245 | channel = 0; | ||
| 246 | if (i2o_dev->lct_data.class_id == | ||
| 247 | I2O_CLASS_RANDOM_BLOCK_STORAGE) | ||
| 248 | lun = i2o_shost->lun++; | ||
| 249 | else | ||
| 250 | lun = 0; | ||
| 251 | } | ||
| 252 | } | ||
| 253 | #endif | ||
| 254 | break; | ||
| 255 | |||
| 256 | case I2O_CLASS_SCSI_PERIPHERAL: | ||
| 257 | if (i2o_parm_field_get(i2o_dev, 0x0000, 3, &id, 4) < 0) | ||
| 258 | return -EFAULT; | ||
| 259 | |||
| 260 | if (i2o_parm_field_get(i2o_dev, 0x0000, 4, &lun, 8) < 0) | ||
| 261 | return -EFAULT; | ||
| 262 | |||
| 263 | parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid); | ||
| 264 | if (!parent) { | ||
| 265 | osm_warn("can not find parent of device %03x\n", | ||
| 266 | i2o_dev->lct_data.tid); | ||
| 267 | return -EFAULT; | ||
| 268 | } | ||
| 269 | |||
| 270 | for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++) | ||
| 271 | if (i2o_shost->channel[i] == parent) | ||
| 272 | channel = i; | ||
| 273 | break; | ||
| 274 | |||
| 275 | default: | ||
| 276 | return -EFAULT; | ||
| 277 | } | ||
| 278 | |||
| 279 | if (channel == -1) { | ||
| 280 | osm_warn("can not find channel of device %03x\n", | ||
| 281 | i2o_dev->lct_data.tid); | ||
| 227 | return -EFAULT; | 282 | return -EFAULT; |
| 283 | } | ||
| 228 | 284 | ||
| 229 | if (id >= scsi_host->max_id) { | 285 | if (id >= scsi_host->max_id) { |
| 230 | osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id, | 286 | osm_warn("SCSI device id (%d) >= max_id of I2O host (%d)", id, |
| @@ -232,31 +288,12 @@ static int i2o_scsi_probe(struct device *dev) | |||
| 232 | return -EFAULT; | 288 | return -EFAULT; |
| 233 | } | 289 | } |
| 234 | 290 | ||
| 235 | if (i2o_parm_field_get(i2o_dev, 0, 4, &lun, 8) < 0) | ||
| 236 | return -EFAULT; | ||
| 237 | if (lun >= scsi_host->max_lun) { | 291 | if (lun >= scsi_host->max_lun) { |
| 238 | osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)", | 292 | osm_warn("SCSI device id (%d) >= max_lun of I2O host (%d)", |
| 239 | (unsigned int)lun, scsi_host->max_lun); | 293 | (unsigned int)lun, scsi_host->max_lun); |
| 240 | return -EFAULT; | 294 | return -EFAULT; |
| 241 | } | 295 | } |
| 242 | 296 | ||
| 243 | parent = i2o_iop_find_device(c, i2o_dev->lct_data.parent_tid); | ||
| 244 | if (!parent) { | ||
| 245 | osm_warn("can not find parent of device %03x\n", | ||
| 246 | i2o_dev->lct_data.tid); | ||
| 247 | return -EFAULT; | ||
| 248 | } | ||
| 249 | |||
| 250 | for (i = 0; i <= i2o_shost->scsi_host->max_channel; i++) | ||
| 251 | if (i2o_shost->channel[i] == parent) | ||
| 252 | channel = i; | ||
| 253 | |||
| 254 | if (channel == -1) { | ||
| 255 | osm_warn("can not find channel of device %03x\n", | ||
| 256 | i2o_dev->lct_data.tid); | ||
| 257 | return -EFAULT; | ||
| 258 | } | ||
| 259 | |||
| 260 | scsi_dev = | 297 | scsi_dev = |
| 261 | __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev); | 298 | __scsi_add_device(i2o_shost->scsi_host, channel, id, lun, i2o_dev); |
| 262 | 299 | ||
| @@ -266,7 +303,8 @@ static int i2o_scsi_probe(struct device *dev) | |||
| 266 | return PTR_ERR(scsi_dev); | 303 | return PTR_ERR(scsi_dev); |
| 267 | } | 304 | } |
| 268 | 305 | ||
| 269 | sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj, "scsi"); | 306 | sysfs_create_link(&i2o_dev->device.kobj, &scsi_dev->sdev_gendev.kobj, |
| 307 | "scsi"); | ||
| 270 | 308 | ||
| 271 | osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n", | 309 | osm_info("device added (TID: %03x) channel: %d, id: %d, lun: %d\n", |
| 272 | i2o_dev->lct_data.tid, channel, id, (unsigned int)lun); | 310 | i2o_dev->lct_data.tid, channel, id, (unsigned int)lun); |
| @@ -542,9 +580,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
| 542 | void (*done) (struct scsi_cmnd *)) | 580 | void (*done) (struct scsi_cmnd *)) |
| 543 | { | 581 | { |
| 544 | struct i2o_controller *c; | 582 | struct i2o_controller *c; |
| 545 | struct Scsi_Host *host; | ||
| 546 | struct i2o_device *i2o_dev; | 583 | struct i2o_device *i2o_dev; |
| 547 | struct device *dev; | ||
| 548 | int tid; | 584 | int tid; |
| 549 | struct i2o_message __iomem *msg; | 585 | struct i2o_message __iomem *msg; |
| 550 | u32 m; | 586 | u32 m; |
| @@ -554,20 +590,16 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
| 554 | * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME | 590 | * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME |
| 555 | */ | 591 | */ |
| 556 | u32 scsi_flags = 0x20a00000; | 592 | u32 scsi_flags = 0x20a00000; |
| 557 | u32 sg_flags; | 593 | u32 sgl_offset; |
| 558 | u32 __iomem *mptr; | 594 | u32 __iomem *mptr; |
| 559 | u32 __iomem *lenptr; | 595 | u32 cmd = I2O_CMD_SCSI_EXEC << 24; |
| 560 | u32 len; | 596 | int rc = 0; |
| 561 | int i; | ||
| 562 | 597 | ||
| 563 | /* | 598 | /* |
| 564 | * Do the incoming paperwork | 599 | * Do the incoming paperwork |
| 565 | */ | 600 | */ |
| 566 | |||
| 567 | i2o_dev = SCpnt->device->hostdata; | 601 | i2o_dev = SCpnt->device->hostdata; |
| 568 | host = SCpnt->device->host; | ||
| 569 | c = i2o_dev->iop; | 602 | c = i2o_dev->iop; |
| 570 | dev = &c->pdev->dev; | ||
| 571 | 603 | ||
| 572 | SCpnt->scsi_done = done; | 604 | SCpnt->scsi_done = done; |
| 573 | 605 | ||
| @@ -575,7 +607,7 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
| 575 | osm_warn("no I2O device in request\n"); | 607 | osm_warn("no I2O device in request\n"); |
| 576 | SCpnt->result = DID_NO_CONNECT << 16; | 608 | SCpnt->result = DID_NO_CONNECT << 16; |
| 577 | done(SCpnt); | 609 | done(SCpnt); |
| 578 | return 0; | 610 | goto exit; |
| 579 | } | 611 | } |
| 580 | 612 | ||
| 581 | tid = i2o_dev->lct_data.tid; | 613 | tid = i2o_dev->lct_data.tid; |
| @@ -584,46 +616,85 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
| 584 | osm_debug("Real scsi messages.\n"); | 616 | osm_debug("Real scsi messages.\n"); |
| 585 | 617 | ||
| 586 | /* | 618 | /* |
| 587 | * Obtain an I2O message. If there are none free then | ||
| 588 | * throw it back to the scsi layer | ||
| 589 | */ | ||
| 590 | |||
| 591 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | ||
| 592 | if (m == I2O_QUEUE_EMPTY) | ||
| 593 | return SCSI_MLQUEUE_HOST_BUSY; | ||
| 594 | |||
| 595 | mptr = &msg->body[0]; | ||
| 596 | |||
| 597 | /* | ||
| 598 | * Put together a scsi execscb message | 619 | * Put together a scsi execscb message |
| 599 | */ | 620 | */ |
| 600 | |||
| 601 | switch (SCpnt->sc_data_direction) { | 621 | switch (SCpnt->sc_data_direction) { |
| 602 | case PCI_DMA_NONE: | 622 | case PCI_DMA_NONE: |
| 603 | /* DATA NO XFER */ | 623 | /* DATA NO XFER */ |
| 604 | sg_flags = 0x00000000; | 624 | sgl_offset = SGL_OFFSET_0; |
| 605 | break; | 625 | break; |
| 606 | 626 | ||
| 607 | case PCI_DMA_TODEVICE: | 627 | case PCI_DMA_TODEVICE: |
| 608 | /* DATA OUT (iop-->dev) */ | 628 | /* DATA OUT (iop-->dev) */ |
| 609 | scsi_flags |= 0x80000000; | 629 | scsi_flags |= 0x80000000; |
| 610 | sg_flags = 0x14000000; | 630 | sgl_offset = SGL_OFFSET_10; |
| 611 | break; | 631 | break; |
| 612 | 632 | ||
| 613 | case PCI_DMA_FROMDEVICE: | 633 | case PCI_DMA_FROMDEVICE: |
| 614 | /* DATA IN (iop<--dev) */ | 634 | /* DATA IN (iop<--dev) */ |
| 615 | scsi_flags |= 0x40000000; | 635 | scsi_flags |= 0x40000000; |
| 616 | sg_flags = 0x10000000; | 636 | sgl_offset = SGL_OFFSET_10; |
| 617 | break; | 637 | break; |
| 618 | 638 | ||
| 619 | default: | 639 | default: |
| 620 | /* Unknown - kill the command */ | 640 | /* Unknown - kill the command */ |
| 621 | SCpnt->result = DID_NO_CONNECT << 16; | 641 | SCpnt->result = DID_NO_CONNECT << 16; |
| 622 | done(SCpnt); | 642 | done(SCpnt); |
| 623 | return 0; | 643 | goto exit; |
| 624 | } | 644 | } |
| 625 | 645 | ||
| 626 | writel(I2O_CMD_SCSI_EXEC << 24 | HOST_TID << 12 | tid, &msg->u.head[1]); | 646 | /* |
| 647 | * Obtain an I2O message. If there are none free then | ||
| 648 | * throw it back to the scsi layer | ||
| 649 | */ | ||
| 650 | |||
| 651 | m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET); | ||
| 652 | if (m == I2O_QUEUE_EMPTY) { | ||
| 653 | rc = SCSI_MLQUEUE_HOST_BUSY; | ||
| 654 | goto exit; | ||
| 655 | } | ||
| 656 | |||
| 657 | mptr = &msg->body[0]; | ||
| 658 | |||
| 659 | #ifdef CONFIG_I2O_EXT_ADAPTEC | ||
| 660 | if (c->adaptec) { | ||
| 661 | u32 adpt_flags = 0; | ||
| 662 | |||
| 663 | if (SCpnt->sc_request && SCpnt->sc_request->upper_private_data) { | ||
| 664 | i2o_sg_io_hdr_t __user *usr_ptr = | ||
| 665 | ((Sg_request *) (SCpnt->sc_request-> | ||
| 666 | upper_private_data))->header. | ||
| 667 | usr_ptr; | ||
| 668 | |||
| 669 | if (usr_ptr) | ||
| 670 | get_user(adpt_flags, &usr_ptr->flags); | ||
| 671 | } | ||
| 672 | |||
| 673 | switch (i2o_dev->lct_data.class_id) { | ||
| 674 | case I2O_CLASS_EXECUTIVE: | ||
| 675 | case I2O_CLASS_RANDOM_BLOCK_STORAGE: | ||
| 676 | /* interpret flag has to be set for executive */ | ||
| 677 | adpt_flags ^= I2O_DPT_SG_FLAG_INTERPRET; | ||
| 678 | break; | ||
| 679 | |||
| 680 | default: | ||
| 681 | break; | ||
| 682 | } | ||
| 683 | |||
| 684 | /* | ||
| 685 | * for Adaptec controllers we use the PRIVATE command, because | ||
| 686 | * the normal SCSI EXEC doesn't support all SCSI commands on | ||
| 687 | * all controllers (for example READ CAPACITY). | ||
| 688 | */ | ||
| 689 | if (sgl_offset == SGL_OFFSET_10) | ||
| 690 | sgl_offset = SGL_OFFSET_12; | ||
| 691 | cmd = I2O_CMD_PRIVATE << 24; | ||
| 692 | writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++); | ||
| 693 | writel(adpt_flags | tid, mptr++); | ||
| 694 | } | ||
| 695 | #endif | ||
| 696 | |||
| 697 | writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]); | ||
| 627 | writel(i2o_scsi_driver.context, &msg->u.s.icntxt); | 698 | writel(i2o_scsi_driver.context, &msg->u.s.icntxt); |
| 628 | 699 | ||
| 629 | /* We want the SCSI control block back */ | 700 | /* We want the SCSI control block back */ |
| @@ -655,55 +726,30 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
| 655 | /* Write SCSI command into the message - always 16 byte block */ | 726 | /* Write SCSI command into the message - always 16 byte block */ |
| 656 | memcpy_toio(mptr, SCpnt->cmnd, 16); | 727 | memcpy_toio(mptr, SCpnt->cmnd, 16); |
| 657 | mptr += 4; | 728 | mptr += 4; |
| 658 | lenptr = mptr++; /* Remember me - fill in when we know */ | ||
| 659 | |||
| 660 | /* Now fill in the SGList and command */ | ||
| 661 | if (SCpnt->use_sg) { | ||
| 662 | struct scatterlist *sg; | ||
| 663 | int sg_count; | ||
| 664 | |||
| 665 | sg = SCpnt->request_buffer; | ||
| 666 | len = 0; | ||
| 667 | 729 | ||
| 668 | sg_count = dma_map_sg(dev, sg, SCpnt->use_sg, | 730 | if (sgl_offset != SGL_OFFSET_0) { |
| 669 | SCpnt->sc_data_direction); | 731 | /* write size of data addressed by SGL */ |
| 670 | 732 | writel(SCpnt->request_bufflen, mptr++); | |
| 671 | if (unlikely(sg_count <= 0)) | 733 | |
| 672 | return -ENOMEM; | 734 | /* Now fill in the SGList and command */ |
| 673 | 735 | if (SCpnt->use_sg) { | |
| 674 | for (i = SCpnt->use_sg; i > 0; i--) { | 736 | if (!i2o_dma_map_sg(c, SCpnt->request_buffer, |
| 675 | if (i == 1) | 737 | SCpnt->use_sg, |
| 676 | sg_flags |= 0xC0000000; | 738 | SCpnt->sc_data_direction, &mptr)) |
| 677 | writel(sg_flags | sg_dma_len(sg), mptr++); | 739 | goto nomem; |
| 678 | writel(sg_dma_address(sg), mptr++); | 740 | } else { |
| 679 | len += sg_dma_len(sg); | 741 | SCpnt->SCp.dma_handle = |
| 680 | sg++; | 742 | i2o_dma_map_single(c, SCpnt->request_buffer, |
| 681 | } | 743 | SCpnt->request_bufflen, |
| 682 | 744 | SCpnt->sc_data_direction, &mptr); | |
| 683 | writel(len, lenptr); | 745 | if (dma_mapping_error(SCpnt->SCp.dma_handle)) |
| 684 | } else { | 746 | goto nomem; |
| 685 | len = SCpnt->request_bufflen; | ||
| 686 | |||
| 687 | writel(len, lenptr); | ||
| 688 | |||
| 689 | if (len > 0) { | ||
| 690 | dma_addr_t dma_addr; | ||
| 691 | |||
| 692 | dma_addr = dma_map_single(dev, SCpnt->request_buffer, | ||
| 693 | SCpnt->request_bufflen, | ||
| 694 | SCpnt->sc_data_direction); | ||
| 695 | if (!dma_addr) | ||
| 696 | return -ENOMEM; | ||
| 697 | |||
| 698 | SCpnt->SCp.ptr = (void *)(unsigned long)dma_addr; | ||
| 699 | sg_flags |= 0xC0000000; | ||
| 700 | writel(sg_flags | SCpnt->request_bufflen, mptr++); | ||
| 701 | writel(dma_addr, mptr++); | ||
| 702 | } | 747 | } |
| 703 | } | 748 | } |
| 704 | 749 | ||
| 705 | /* Stick the headers on */ | 750 | /* Stick the headers on */ |
| 706 | writel((mptr - &msg->u.head[0]) << 16 | SGL_OFFSET_10, &msg->u.head[0]); | 751 | writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset, |
| 752 | &msg->u.head[0]); | ||
| 707 | 753 | ||
| 708 | /* Queue the message */ | 754 | /* Queue the message */ |
| 709 | i2o_msg_post(c, m); | 755 | i2o_msg_post(c, m); |
| @@ -711,6 +757,13 @@ static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt, | |||
| 711 | osm_debug("Issued %ld\n", SCpnt->serial_number); | 757 | osm_debug("Issued %ld\n", SCpnt->serial_number); |
| 712 | 758 | ||
| 713 | return 0; | 759 | return 0; |
| 760 | |||
| 761 | nomem: | ||
| 762 | rc = -ENOMEM; | ||
| 763 | i2o_msg_nop(c, m); | ||
| 764 | |||
| 765 | exit: | ||
| 766 | return rc; | ||
| 714 | }; | 767 | }; |
| 715 | 768 | ||
| 716 | /** | 769 | /** |
diff --git a/drivers/message/i2o/pci.c b/drivers/message/i2o/pci.c index a499af096a..964fe48184 100644 --- a/drivers/message/i2o/pci.c +++ b/drivers/message/i2o/pci.c | |||
| @@ -362,11 +362,33 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev, | |||
| 362 | c->promise = 1; | 362 | c->promise = 1; |
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | if (pdev->subsystem_vendor == PCI_VENDOR_ID_DPT) | ||
| 366 | c->adaptec = 1; | ||
| 367 | |||
| 365 | /* Cards that go bananas if you quiesce them before you reset them. */ | 368 | /* Cards that go bananas if you quiesce them before you reset them. */ |
| 366 | if (pdev->vendor == PCI_VENDOR_ID_DPT) { | 369 | if (pdev->vendor == PCI_VENDOR_ID_DPT) { |
| 367 | c->no_quiesce = 1; | 370 | c->no_quiesce = 1; |
| 368 | if (pdev->device == 0xa511) | 371 | if (pdev->device == 0xa511) |
| 369 | c->raptor = 1; | 372 | c->raptor = 1; |
| 373 | |||
| 374 | if (pdev->subsystem_device == 0xc05a) { | ||
| 375 | c->limit_sectors = 1; | ||
| 376 | printk(KERN_INFO | ||
| 377 | "%s: limit sectors per request to %d\n", c->name, | ||
| 378 | I2O_MAX_SECTORS_LIMITED); | ||
| 379 | } | ||
| 380 | #ifdef CONFIG_I2O_EXT_ADAPTEC_DMA64 | ||
| 381 | if (sizeof(dma_addr_t) > 4) { | ||
| 382 | if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)) | ||
| 383 | printk(KERN_INFO "%s: 64-bit DMA unavailable\n", | ||
| 384 | c->name); | ||
| 385 | else { | ||
| 386 | c->pae_support = 1; | ||
| 387 | printk(KERN_INFO "%s: using 64-bit DMA\n", | ||
| 388 | c->name); | ||
| 389 | } | ||
| 390 | } | ||
| 391 | #endif | ||
| 370 | } | 392 | } |
| 371 | 393 | ||
| 372 | if ((rc = i2o_pci_alloc(c))) { | 394 | if ((rc = i2o_pci_alloc(c))) { |
diff --git a/include/linux/i2o-dev.h b/include/linux/i2o-dev.h index 90c984ecd5..d4a08d29e3 100644 --- a/include/linux/i2o-dev.h +++ b/include/linux/i2o-dev.h | |||
| @@ -33,6 +33,13 @@ typedef unsigned int u32; | |||
| 33 | #endif /* __KERNEL__ */ | 33 | #endif /* __KERNEL__ */ |
| 34 | 34 | ||
| 35 | /* | 35 | /* |
| 36 | * Software module types | ||
| 37 | */ | ||
| 38 | #define I2O_SOFTWARE_MODULE_IRTOS 0x11 | ||
| 39 | #define I2O_SOFTWARE_MODULE_IOP_PRIVATE 0x22 | ||
| 40 | #define I2O_SOFTWARE_MODULE_IOP_CONFIG 0x23 | ||
| 41 | |||
| 42 | /* | ||
| 36 | * Vendors | 43 | * Vendors |
| 37 | */ | 44 | */ |
| 38 | #define I2O_VENDOR_DPT 0x001b | 45 | #define I2O_VENDOR_DPT 0x001b |
| @@ -125,6 +132,10 @@ struct i2o_evt_get { | |||
| 125 | int lost; | 132 | int lost; |
| 126 | }; | 133 | }; |
| 127 | 134 | ||
| 135 | typedef struct i2o_sg_io_hdr { | ||
| 136 | unsigned int flags; /* see I2O_DPT_SG_IO_FLAGS */ | ||
| 137 | } i2o_sg_io_hdr_t; | ||
| 138 | |||
| 128 | /************************************************************************** | 139 | /************************************************************************** |
| 129 | * HRT related constants and structures | 140 | * HRT related constants and structures |
| 130 | **************************************************************************/ | 141 | **************************************************************************/ |
| @@ -403,4 +414,15 @@ typedef struct _i2o_status_block { | |||
| 403 | #define ADAPTER_STATE_FAILED 0x10 | 414 | #define ADAPTER_STATE_FAILED 0x10 |
| 404 | #define ADAPTER_STATE_FAULTED 0x11 | 415 | #define ADAPTER_STATE_FAULTED 0x11 |
| 405 | 416 | ||
| 417 | |||
| 418 | /* | ||
| 419 | * DPT / Adaptec specific values for i2o_sg_io_hdr flags. | ||
| 420 | */ | ||
| 421 | #define I2O_DPT_SG_FLAG_INTERPRET 0x00010000 | ||
| 422 | #define I2O_DPT_SG_FLAG_PHYSICAL 0x00020000 | ||
| 423 | |||
| 424 | #define I2O_DPT_FLASH_FRAG_SIZE 0x10000 | ||
| 425 | #define I2O_DPT_FLASH_READ 0x0101 | ||
| 426 | #define I2O_DPT_FLASH_WRITE 0x0102 | ||
| 427 | |||
| 406 | #endif /* _I2O_DEV_H */ | 428 | #endif /* _I2O_DEV_H */ |
diff --git a/include/linux/i2o.h b/include/linux/i2o.h index 497ea574f9..2039a87c2b 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h | |||
| @@ -147,10 +147,13 @@ struct i2o_controller { | |||
| 147 | 147 | ||
| 148 | struct pci_dev *pdev; /* PCI device */ | 148 | struct pci_dev *pdev; /* PCI device */ |
| 149 | 149 | ||
| 150 | unsigned int short_req:1; /* use small block sizes */ | ||
| 151 | unsigned int no_quiesce:1; /* dont quiesce before reset */ | ||
| 152 | unsigned int raptor:1; /* split bar */ | ||
| 153 | unsigned int promise:1; /* Promise controller */ | 150 | unsigned int promise:1; /* Promise controller */ |
| 151 | unsigned int adaptec:1; /* DPT / Adaptec controller */ | ||
| 152 | unsigned int raptor:1; /* split bar */ | ||
| 153 | unsigned int no_quiesce:1; /* dont quiesce before reset */ | ||
| 154 | unsigned int short_req:1; /* use small block sizes */ | ||
| 155 | unsigned int limit_sectors:1; /* limit number of sectors / request */ | ||
| 156 | unsigned int pae_support:1; /* controller has 64-bit SGL support */ | ||
| 154 | 157 | ||
| 155 | struct list_head devices; /* list of I2O devices */ | 158 | struct list_head devices; /* list of I2O devices */ |
| 156 | struct list_head list; /* Controller list */ | 159 | struct list_head list; /* Controller list */ |
| @@ -746,7 +749,21 @@ static inline struct i2o_message __iomem *i2o_msg_in_to_virt(struct i2o_controll | |||
| 746 | static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, | 749 | static inline int i2o_dma_alloc(struct device *dev, struct i2o_dma *addr, |
| 747 | size_t len, unsigned int gfp_mask) | 750 | size_t len, unsigned int gfp_mask) |
| 748 | { | 751 | { |
| 752 | struct pci_dev *pdev = to_pci_dev(dev); | ||
| 753 | int dma_64 = 0; | ||
| 754 | |||
| 755 | if ((sizeof(dma_addr_t) > 4) && (pdev->dma_mask == DMA_64BIT_MASK)) { | ||
| 756 | dma_64 = 1; | ||
| 757 | if(pci_set_dma_mask(pdev, DMA_32BIT_MASK)) | ||
| 758 | return -ENOMEM; | ||
| 759 | } | ||
| 760 | |||
| 749 | addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask); | 761 | addr->virt = dma_alloc_coherent(dev, len, &addr->phys, gfp_mask); |
| 762 | |||
| 763 | if ((sizeof(dma_addr_t) > 4) && dma_64) | ||
| 764 | if(pci_set_dma_mask(pdev, DMA_64BIT_MASK)) | ||
| 765 | printk(KERN_WARNING "i2o: unable to set 64-bit DMA"); | ||
| 766 | |||
| 750 | if (!addr->virt) | 767 | if (!addr->virt) |
| 751 | return -ENOMEM; | 768 | return -ENOMEM; |
| 752 | 769 | ||
| @@ -946,7 +963,7 @@ extern void i2o_debug_state(struct i2o_controller *c); | |||
| 946 | #define I2O_CMD_BLOCK_MEJECT 0x43 | 963 | #define I2O_CMD_BLOCK_MEJECT 0x43 |
| 947 | #define I2O_CMD_BLOCK_POWER 0x70 | 964 | #define I2O_CMD_BLOCK_POWER 0x70 |
| 948 | 965 | ||
| 949 | #define I2O_PRIVATE_MSG 0xFF | 966 | #define I2O_CMD_PRIVATE 0xFF |
| 950 | 967 | ||
| 951 | /* Command status values */ | 968 | /* Command status values */ |
| 952 | 969 | ||
| @@ -1095,9 +1112,9 @@ extern void i2o_debug_state(struct i2o_controller *c); | |||
| 1095 | #define SGL_OFFSET_8 (0x0080 | I2OVERSION) | 1112 | #define SGL_OFFSET_8 (0x0080 | I2OVERSION) |
| 1096 | #define SGL_OFFSET_9 (0x0090 | I2OVERSION) | 1113 | #define SGL_OFFSET_9 (0x0090 | I2OVERSION) |
| 1097 | #define SGL_OFFSET_10 (0x00A0 | I2OVERSION) | 1114 | #define SGL_OFFSET_10 (0x00A0 | I2OVERSION) |
| 1098 | 1115 | #define SGL_OFFSET_11 (0x00B0 | I2OVERSION) | |
| 1099 | #define TRL_OFFSET_5 (0x0050 | I2OVERSION) | 1116 | #define SGL_OFFSET_12 (0x00C0 | I2OVERSION) |
| 1100 | #define TRL_OFFSET_6 (0x0060 | I2OVERSION) | 1117 | #define SGL_OFFSET(x) (((x)<<4) | I2OVERSION) |
| 1101 | 1118 | ||
| 1102 | /* Transaction Reply Lists (TRL) Control Word structure */ | 1119 | /* Transaction Reply Lists (TRL) Control Word structure */ |
| 1103 | #define TRL_SINGLE_FIXED_LENGTH 0x00 | 1120 | #define TRL_SINGLE_FIXED_LENGTH 0x00 |
| @@ -1130,7 +1147,6 @@ extern void i2o_debug_state(struct i2o_controller *c); | |||
| 1130 | #define HOST_TID 1 | 1147 | #define HOST_TID 1 |
| 1131 | 1148 | ||
| 1132 | #define MSG_FRAME_SIZE 128 /* i2o_scsi assumes >= 32 */ | 1149 | #define MSG_FRAME_SIZE 128 /* i2o_scsi assumes >= 32 */ |
| 1133 | #define REPLY_FRAME_SIZE 17 | ||
| 1134 | #define SG_TABLESIZE 30 | 1150 | #define SG_TABLESIZE 30 |
| 1135 | #define NMBR_MSG_FRAMES 128 | 1151 | #define NMBR_MSG_FRAMES 128 |
| 1136 | 1152 | ||
| @@ -1155,11 +1171,10 @@ extern void i2o_debug_state(struct i2o_controller *c); | |||
| 1155 | #define I2O_HRT_GET_TRIES 3 | 1171 | #define I2O_HRT_GET_TRIES 3 |
| 1156 | #define I2O_LCT_GET_TRIES 3 | 1172 | #define I2O_LCT_GET_TRIES 3 |
| 1157 | 1173 | ||
| 1158 | /* request queue sizes */ | 1174 | /* defines for max_sectors and max_phys_segments */ |
| 1159 | #define I2O_MAX_SECTORS 1024 | 1175 | #define I2O_MAX_SECTORS 1024 |
| 1176 | #define I2O_MAX_SECTORS_LIMITED 256 | ||
| 1160 | #define I2O_MAX_PHYS_SEGMENTS MAX_PHYS_SEGMENTS | 1177 | #define I2O_MAX_PHYS_SEGMENTS MAX_PHYS_SEGMENTS |
| 1161 | 1178 | ||
| 1162 | #define I2O_REQ_MEMPOOL_SIZE 32 | ||
| 1163 | |||
| 1164 | #endif /* __KERNEL__ */ | 1179 | #endif /* __KERNEL__ */ |
| 1165 | #endif /* _I2O_H */ | 1180 | #endif /* _I2O_H */ |
diff --git a/include/scsi/sg_request.h b/include/scsi/sg_request.h new file mode 100644 index 0000000000..57ff525bdd --- /dev/null +++ b/include/scsi/sg_request.h | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | typedef struct scsi_request Scsi_Request; | ||
| 2 | |||
| 3 | static Scsi_Request *dummy_cmdp; /* only used for sizeof */ | ||
| 4 | |||
| 5 | typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */ | ||
| 6 | unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */ | ||
| 7 | unsigned short sglist_len; /* size of malloc'd scatter-gather list ++ */ | ||
| 8 | unsigned bufflen; /* Size of (aggregate) data buffer */ | ||
| 9 | unsigned b_malloc_len; /* actual len malloc'ed in buffer */ | ||
| 10 | void *buffer; /* Data buffer or scatter list (k_use_sg>0) */ | ||
| 11 | char dio_in_use; /* 0->indirect IO (or mmap), 1->dio */ | ||
| 12 | unsigned char cmd_opcode; /* first byte of command */ | ||
| 13 | } Sg_scatter_hold; | ||
| 14 | |||
| 15 | typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */ | ||
| 16 | Scsi_Request *my_cmdp; /* != 0 when request with lower levels */ | ||
| 17 | struct sg_request *nextrp; /* NULL -> tail request (slist) */ | ||
| 18 | struct sg_fd *parentfp; /* NULL -> not in use */ | ||
| 19 | Sg_scatter_hold data; /* hold buffer, perhaps scatter list */ | ||
| 20 | sg_io_hdr_t header; /* scsi command+info, see <scsi/sg.h> */ | ||
| 21 | unsigned char sense_b[sizeof (dummy_cmdp->sr_sense_buffer)]; | ||
| 22 | char res_used; /* 1 -> using reserve buffer, 0 -> not ... */ | ||
| 23 | char orphan; /* 1 -> drop on sight, 0 -> normal */ | ||
| 24 | char sg_io_owned; /* 1 -> packet belongs to SG_IO */ | ||
| 25 | volatile char done; /* 0->before bh, 1->before read, 2->read */ | ||
| 26 | } Sg_request; | ||
