aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/cciss.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/block/cciss.c')
-rw-r--r--drivers/block/cciss.c218
1 files changed, 107 insertions, 111 deletions
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c
index 9291614ac6b7..9e3af307aae1 100644
--- a/drivers/block/cciss.c
+++ b/drivers/block/cciss.c
@@ -257,6 +257,79 @@ static inline void removeQ(CommandList_struct *c)
257 hlist_del_init(&c->list); 257 hlist_del_init(&c->list);
258} 258}
259 259
260static void cciss_free_sg_chain_blocks(SGDescriptor_struct **cmd_sg_list,
261 int nr_cmds)
262{
263 int i;
264
265 if (!cmd_sg_list)
266 return;
267 for (i = 0; i < nr_cmds; i++) {
268 kfree(cmd_sg_list[i]);
269 cmd_sg_list[i] = NULL;
270 }
271 kfree(cmd_sg_list);
272}
273
274static SGDescriptor_struct **cciss_allocate_sg_chain_blocks(
275 ctlr_info_t *h, int chainsize, int nr_cmds)
276{
277 int j;
278 SGDescriptor_struct **cmd_sg_list;
279
280 if (chainsize <= 0)
281 return NULL;
282
283 cmd_sg_list = kmalloc(sizeof(*cmd_sg_list) * nr_cmds, GFP_KERNEL);
284 if (!cmd_sg_list)
285 return NULL;
286
287 /* Build up chain blocks for each command */
288 for (j = 0; j < nr_cmds; j++) {
289 /* Need a block of chainsized s/g elements. */
290 cmd_sg_list[j] = kmalloc((chainsize *
291 sizeof(*cmd_sg_list[j])), GFP_KERNEL);
292 if (!cmd_sg_list[j]) {
293 dev_err(&h->pdev->dev, "Cannot get memory "
294 "for s/g chains.\n");
295 goto clean;
296 }
297 }
298 return cmd_sg_list;
299clean:
300 cciss_free_sg_chain_blocks(cmd_sg_list, nr_cmds);
301 return NULL;
302}
303
304static void cciss_unmap_sg_chain_block(ctlr_info_t *h, CommandList_struct *c)
305{
306 SGDescriptor_struct *chain_sg;
307 u64bit temp64;
308
309 if (c->Header.SGTotal <= h->max_cmd_sgentries)
310 return;
311
312 chain_sg = &c->SG[h->max_cmd_sgentries - 1];
313 temp64.val32.lower = chain_sg->Addr.lower;
314 temp64.val32.upper = chain_sg->Addr.upper;
315 pci_unmap_single(h->pdev, temp64.val, chain_sg->Len, PCI_DMA_TODEVICE);
316}
317
318static void cciss_map_sg_chain_block(ctlr_info_t *h, CommandList_struct *c,
319 SGDescriptor_struct *chain_block, int len)
320{
321 SGDescriptor_struct *chain_sg;
322 u64bit temp64;
323
324 chain_sg = &c->SG[h->max_cmd_sgentries - 1];
325 chain_sg->Ext = CCISS_SG_CHAIN;
326 chain_sg->Len = len;
327 temp64.val = pci_map_single(h->pdev, chain_block, len,
328 PCI_DMA_TODEVICE);
329 chain_sg->Addr.lower = temp64.val32.lower;
330 chain_sg->Addr.upper = temp64.val32.upper;
331}
332
260#include "cciss_scsi.c" /* For SCSI tape support */ 333#include "cciss_scsi.c" /* For SCSI tape support */
261 334
262static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG", 335static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
@@ -1344,26 +1417,27 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
1344 kfree(buff); 1417 kfree(buff);
1345 return -ENOMEM; 1418 return -ENOMEM;
1346 } 1419 }
1347 // Fill in the command type 1420 /* Fill in the command type */
1348 c->cmd_type = CMD_IOCTL_PEND; 1421 c->cmd_type = CMD_IOCTL_PEND;
1349 // Fill in Command Header 1422 /* Fill in Command Header */
1350 c->Header.ReplyQueue = 0; // unused in simple mode 1423 c->Header.ReplyQueue = 0; /* unused in simple mode */
1351 if (iocommand.buf_size > 0) // buffer to fill 1424 if (iocommand.buf_size > 0) /* buffer to fill */
1352 { 1425 {
1353 c->Header.SGList = 1; 1426 c->Header.SGList = 1;
1354 c->Header.SGTotal = 1; 1427 c->Header.SGTotal = 1;
1355 } else // no buffers to fill 1428 } else /* no buffers to fill */
1356 { 1429 {
1357 c->Header.SGList = 0; 1430 c->Header.SGList = 0;
1358 c->Header.SGTotal = 0; 1431 c->Header.SGTotal = 0;
1359 } 1432 }
1360 c->Header.LUN = iocommand.LUN_info; 1433 c->Header.LUN = iocommand.LUN_info;
1361 c->Header.Tag.lower = c->busaddr; // use the kernel address the cmd block for tag 1434 /* use the kernel address the cmd block for tag */
1435 c->Header.Tag.lower = c->busaddr;
1362 1436
1363 // Fill in Request block 1437 /* Fill in Request block */
1364 c->Request = iocommand.Request; 1438 c->Request = iocommand.Request;
1365 1439
1366 // Fill in the scatter gather information 1440 /* Fill in the scatter gather information */
1367 if (iocommand.buf_size > 0) { 1441 if (iocommand.buf_size > 0) {
1368 temp64.val = pci_map_single(host->pdev, buff, 1442 temp64.val = pci_map_single(host->pdev, buff,
1369 iocommand.buf_size, 1443 iocommand.buf_size,
@@ -1371,7 +1445,7 @@ static int cciss_ioctl(struct block_device *bdev, fmode_t mode,
1371 c->SG[0].Addr.lower = temp64.val32.lower; 1445 c->SG[0].Addr.lower = temp64.val32.lower;
1372 c->SG[0].Addr.upper = temp64.val32.upper; 1446 c->SG[0].Addr.upper = temp64.val32.upper;
1373 c->SG[0].Len = iocommand.buf_size; 1447 c->SG[0].Len = iocommand.buf_size;
1374 c->SG[0].Ext = 0; // we are not chaining 1448 c->SG[0].Ext = 0; /* we are not chaining */
1375 } 1449 }
1376 c->waiting = &wait; 1450 c->waiting = &wait;
1377 1451
@@ -1670,14 +1744,9 @@ static void cciss_softirq_done(struct request *rq)
1670 /* unmap the DMA mapping for all the scatter gather elements */ 1744 /* unmap the DMA mapping for all the scatter gather elements */
1671 for (i = 0; i < cmd->Header.SGList; i++) { 1745 for (i = 0; i < cmd->Header.SGList; i++) {
1672 if (curr_sg[sg_index].Ext == CCISS_SG_CHAIN) { 1746 if (curr_sg[sg_index].Ext == CCISS_SG_CHAIN) {
1673 temp64.val32.lower = cmd->SG[i].Addr.lower; 1747 cciss_unmap_sg_chain_block(h, cmd);
1674 temp64.val32.upper = cmd->SG[i].Addr.upper;
1675 pci_dma_sync_single_for_cpu(h->pdev, temp64.val,
1676 cmd->SG[i].Len, ddir);
1677 pci_unmap_single(h->pdev, temp64.val,
1678 cmd->SG[i].Len, ddir);
1679 /* Point to the next block */ 1748 /* Point to the next block */
1680 curr_sg = h->cmd_sg_list[cmd->cmdindex]->sgchain; 1749 curr_sg = h->cmd_sg_list[cmd->cmdindex];
1681 sg_index = 0; 1750 sg_index = 0;
1682 } 1751 }
1683 temp64.val32.lower = curr_sg[sg_index].Addr.lower; 1752 temp64.val32.lower = curr_sg[sg_index].Addr.lower;
@@ -1796,12 +1865,9 @@ static int cciss_add_disk(ctlr_info_t *h, struct gendisk *disk,
1796 blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); 1865 blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask);
1797 1866
1798 /* This is a hardware imposed limit. */ 1867 /* This is a hardware imposed limit. */
1799 blk_queue_max_hw_segments(disk->queue, h->maxsgentries); 1868 blk_queue_max_segments(disk->queue, h->maxsgentries);
1800
1801 /* This is a limit in the driver and could be eliminated. */
1802 blk_queue_max_phys_segments(disk->queue, h->maxsgentries);
1803 1869
1804 blk_queue_max_sectors(disk->queue, h->cciss_max_sectors); 1870 blk_queue_max_hw_sectors(disk->queue, h->cciss_max_sectors);
1805 1871
1806 blk_queue_softirq_done(disk->queue, cciss_softirq_done); 1872 blk_queue_softirq_done(disk->queue, cciss_softirq_done);
1807 1873
@@ -2425,7 +2491,7 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff,
2425 c->Request.Type.Direction = XFER_READ; 2491 c->Request.Type.Direction = XFER_READ;
2426 c->Request.Timeout = 0; 2492 c->Request.Timeout = 0;
2427 c->Request.CDB[0] = cmd; 2493 c->Request.CDB[0] = cmd;
2428 c->Request.CDB[6] = (size >> 24) & 0xFF; //MSB 2494 c->Request.CDB[6] = (size >> 24) & 0xFF; /* MSB */
2429 c->Request.CDB[7] = (size >> 16) & 0xFF; 2495 c->Request.CDB[7] = (size >> 16) & 0xFF;
2430 c->Request.CDB[8] = (size >> 8) & 0xFF; 2496 c->Request.CDB[8] = (size >> 8) & 0xFF;
2431 c->Request.CDB[9] = size & 0xFF; 2497 c->Request.CDB[9] = size & 0xFF;
@@ -2694,7 +2760,7 @@ static void cciss_geometry_inquiry(int ctlr, int logvol,
2694 "cciss: reading geometry failed, volume " 2760 "cciss: reading geometry failed, volume "
2695 "does not support reading geometry\n"); 2761 "does not support reading geometry\n");
2696 drv->heads = 255; 2762 drv->heads = 255;
2697 drv->sectors = 32; // Sectors per track 2763 drv->sectors = 32; /* Sectors per track */
2698 drv->cylinders = total_size + 1; 2764 drv->cylinders = total_size + 1;
2699 drv->raid_level = RAID_UNKNOWN; 2765 drv->raid_level = RAID_UNKNOWN;
2700 } else { 2766 } else {
@@ -3082,7 +3148,6 @@ static void do_cciss_request(struct request_queue *q)
3082 SGDescriptor_struct *curr_sg; 3148 SGDescriptor_struct *curr_sg;
3083 drive_info_struct *drv; 3149 drive_info_struct *drv;
3084 int i, dir; 3150 int i, dir;
3085 int nseg = 0;
3086 int sg_index = 0; 3151 int sg_index = 0;
3087 int chained = 0; 3152 int chained = 0;
3088 3153
@@ -3112,19 +3177,19 @@ static void do_cciss_request(struct request_queue *q)
3112 3177
3113 /* fill in the request */ 3178 /* fill in the request */
3114 drv = creq->rq_disk->private_data; 3179 drv = creq->rq_disk->private_data;
3115 c->Header.ReplyQueue = 0; // unused in simple mode 3180 c->Header.ReplyQueue = 0; /* unused in simple mode */
3116 /* got command from pool, so use the command block index instead */ 3181 /* got command from pool, so use the command block index instead */
3117 /* for direct lookups. */ 3182 /* for direct lookups. */
3118 /* The first 2 bits are reserved for controller error reporting. */ 3183 /* The first 2 bits are reserved for controller error reporting. */
3119 c->Header.Tag.lower = (c->cmdindex << 3); 3184 c->Header.Tag.lower = (c->cmdindex << 3);
3120 c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */ 3185 c->Header.Tag.lower |= 0x04; /* flag for direct lookup. */
3121 memcpy(&c->Header.LUN, drv->LunID, sizeof(drv->LunID)); 3186 memcpy(&c->Header.LUN, drv->LunID, sizeof(drv->LunID));
3122 c->Request.CDBLen = 10; // 12 byte commands not in FW yet; 3187 c->Request.CDBLen = 10; /* 12 byte commands not in FW yet; */
3123 c->Request.Type.Type = TYPE_CMD; // It is a command. 3188 c->Request.Type.Type = TYPE_CMD; /* It is a command. */
3124 c->Request.Type.Attribute = ATTR_SIMPLE; 3189 c->Request.Type.Attribute = ATTR_SIMPLE;
3125 c->Request.Type.Direction = 3190 c->Request.Type.Direction =
3126 (rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE; 3191 (rq_data_dir(creq) == READ) ? XFER_READ : XFER_WRITE;
3127 c->Request.Timeout = 0; // Don't time out 3192 c->Request.Timeout = 0; /* Don't time out */
3128 c->Request.CDB[0] = 3193 c->Request.CDB[0] =
3129 (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write; 3194 (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write;
3130 start_blk = blk_rq_pos(creq); 3195 start_blk = blk_rq_pos(creq);
@@ -3149,13 +3214,8 @@ static void do_cciss_request(struct request_queue *q)
3149 for (i = 0; i < seg; i++) { 3214 for (i = 0; i < seg; i++) {
3150 if (((sg_index+1) == (h->max_cmd_sgentries)) && 3215 if (((sg_index+1) == (h->max_cmd_sgentries)) &&
3151 !chained && ((seg - i) > 1)) { 3216 !chained && ((seg - i) > 1)) {
3152 nseg = seg - i;
3153 curr_sg[sg_index].Len = (nseg) *
3154 sizeof(SGDescriptor_struct);
3155 curr_sg[sg_index].Ext = CCISS_SG_CHAIN;
3156
3157 /* Point to next chain block. */ 3217 /* Point to next chain block. */
3158 curr_sg = h->cmd_sg_list[c->cmdindex]->sgchain; 3218 curr_sg = h->cmd_sg_list[c->cmdindex];
3159 sg_index = 0; 3219 sg_index = 0;
3160 chained = 1; 3220 chained = 1;
3161 } 3221 }
@@ -3166,31 +3226,12 @@ static void do_cciss_request(struct request_queue *q)
3166 curr_sg[sg_index].Addr.lower = temp64.val32.lower; 3226 curr_sg[sg_index].Addr.lower = temp64.val32.lower;
3167 curr_sg[sg_index].Addr.upper = temp64.val32.upper; 3227 curr_sg[sg_index].Addr.upper = temp64.val32.upper;
3168 curr_sg[sg_index].Ext = 0; /* we are not chaining */ 3228 curr_sg[sg_index].Ext = 0; /* we are not chaining */
3169
3170 ++sg_index; 3229 ++sg_index;
3171 } 3230 }
3172 3231 if (chained)
3173 if (chained) { 3232 cciss_map_sg_chain_block(h, c, h->cmd_sg_list[c->cmdindex],
3174 int len; 3233 (seg - (h->max_cmd_sgentries - 1)) *
3175 curr_sg = c->SG; 3234 sizeof(SGDescriptor_struct));
3176 sg_index = h->max_cmd_sgentries - 1;
3177 len = curr_sg[sg_index].Len;
3178 /* Setup pointer to next chain block.
3179 * Fill out last element in current chain
3180 * block with address of next chain block.
3181 */
3182 temp64.val = pci_map_single(h->pdev,
3183 h->cmd_sg_list[c->cmdindex]->sgchain,
3184 len, dir);
3185
3186 h->cmd_sg_list[c->cmdindex]->sg_chain_dma = temp64.val;
3187 curr_sg[sg_index].Addr.lower = temp64.val32.lower;
3188 curr_sg[sg_index].Addr.upper = temp64.val32.upper;
3189
3190 pci_dma_sync_single_for_device(h->pdev,
3191 h->cmd_sg_list[c->cmdindex]->sg_chain_dma,
3192 len, dir);
3193 }
3194 3235
3195 /* track how many SG entries we are using */ 3236 /* track how many SG entries we are using */
3196 if (seg > h->maxSG) 3237 if (seg > h->maxSG)
@@ -3209,11 +3250,11 @@ static void do_cciss_request(struct request_queue *q)
3209 if (likely(blk_fs_request(creq))) { 3250 if (likely(blk_fs_request(creq))) {
3210 if(h->cciss_read == CCISS_READ_10) { 3251 if(h->cciss_read == CCISS_READ_10) {
3211 c->Request.CDB[1] = 0; 3252 c->Request.CDB[1] = 0;
3212 c->Request.CDB[2] = (start_blk >> 24) & 0xff; //MSB 3253 c->Request.CDB[2] = (start_blk >> 24) & 0xff; /* MSB */
3213 c->Request.CDB[3] = (start_blk >> 16) & 0xff; 3254 c->Request.CDB[3] = (start_blk >> 16) & 0xff;
3214 c->Request.CDB[4] = (start_blk >> 8) & 0xff; 3255 c->Request.CDB[4] = (start_blk >> 8) & 0xff;
3215 c->Request.CDB[5] = start_blk & 0xff; 3256 c->Request.CDB[5] = start_blk & 0xff;
3216 c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB 3257 c->Request.CDB[6] = 0; /* (sect >> 24) & 0xff; MSB */
3217 c->Request.CDB[7] = (blk_rq_sectors(creq) >> 8) & 0xff; 3258 c->Request.CDB[7] = (blk_rq_sectors(creq) >> 8) & 0xff;
3218 c->Request.CDB[8] = blk_rq_sectors(creq) & 0xff; 3259 c->Request.CDB[8] = blk_rq_sectors(creq) & 0xff;
3219 c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; 3260 c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
@@ -3222,7 +3263,7 @@ static void do_cciss_request(struct request_queue *q)
3222 3263
3223 c->Request.CDBLen = 16; 3264 c->Request.CDBLen = 16;
3224 c->Request.CDB[1]= 0; 3265 c->Request.CDB[1]= 0;
3225 c->Request.CDB[2]= (upper32 >> 24) & 0xff; //MSB 3266 c->Request.CDB[2]= (upper32 >> 24) & 0xff; /* MSB */
3226 c->Request.CDB[3]= (upper32 >> 16) & 0xff; 3267 c->Request.CDB[3]= (upper32 >> 16) & 0xff;
3227 c->Request.CDB[4]= (upper32 >> 8) & 0xff; 3268 c->Request.CDB[4]= (upper32 >> 8) & 0xff;
3228 c->Request.CDB[5]= upper32 & 0xff; 3269 c->Request.CDB[5]= upper32 & 0xff;
@@ -4240,37 +4281,10 @@ static int __devinit cciss_init_one(struct pci_dev *pdev,
4240 goto clean4; 4281 goto clean4;
4241 } 4282 }
4242 } 4283 }
4243 hba[i]->cmd_sg_list = kmalloc(sizeof(struct Cmd_sg_list *) * 4284 hba[i]->cmd_sg_list = cciss_allocate_sg_chain_blocks(hba[i],
4244 hba[i]->nr_cmds, 4285 hba[i]->chainsize, hba[i]->nr_cmds);
4245 GFP_KERNEL); 4286 if (!hba[i]->cmd_sg_list && hba[i]->chainsize > 0)
4246 if (!hba[i]->cmd_sg_list) {
4247 printk(KERN_ERR "cciss%d: Cannot get memory for "
4248 "s/g chaining.\n", i);
4249 goto clean4; 4287 goto clean4;
4250 }
4251 /* Build up chain blocks for each command */
4252 if (hba[i]->chainsize > 0) {
4253 for (j = 0; j < hba[i]->nr_cmds; j++) {
4254 hba[i]->cmd_sg_list[j] =
4255 kmalloc(sizeof(struct Cmd_sg_list),
4256 GFP_KERNEL);
4257 if (!hba[i]->cmd_sg_list[j]) {
4258 printk(KERN_ERR "cciss%d: Cannot get memory "
4259 "for chain block.\n", i);
4260 goto clean4;
4261 }
4262 /* Need a block of chainsized s/g elements. */
4263 hba[i]->cmd_sg_list[j]->sgchain =
4264 kmalloc((hba[i]->chainsize *
4265 sizeof(SGDescriptor_struct)),
4266 GFP_KERNEL);
4267 if (!hba[i]->cmd_sg_list[j]->sgchain) {
4268 printk(KERN_ERR "cciss%d: Cannot get memory "
4269 "for s/g chains\n", i);
4270 goto clean4;
4271 }
4272 }
4273 }
4274 4288
4275 spin_lock_init(&hba[i]->lock); 4289 spin_lock_init(&hba[i]->lock);
4276 4290
@@ -4329,16 +4343,7 @@ clean4:
4329 for (k = 0; k < hba[i]->nr_cmds; k++) 4343 for (k = 0; k < hba[i]->nr_cmds; k++)
4330 kfree(hba[i]->scatter_list[k]); 4344 kfree(hba[i]->scatter_list[k]);
4331 kfree(hba[i]->scatter_list); 4345 kfree(hba[i]->scatter_list);
4332 /* Only free up extra s/g lists if controller supports them */ 4346 cciss_free_sg_chain_blocks(hba[i]->cmd_sg_list, hba[i]->nr_cmds);
4333 if (hba[i]->chainsize > 0) {
4334 for (j = 0; j < hba[i]->nr_cmds; j++) {
4335 if (hba[i]->cmd_sg_list[j]) {
4336 kfree(hba[i]->cmd_sg_list[j]->sgchain);
4337 kfree(hba[i]->cmd_sg_list[j]);
4338 }
4339 }
4340 kfree(hba[i]->cmd_sg_list);
4341 }
4342 if (hba[i]->cmd_pool) 4347 if (hba[i]->cmd_pool)
4343 pci_free_consistent(hba[i]->pdev, 4348 pci_free_consistent(hba[i]->pdev,
4344 hba[i]->nr_cmds * sizeof(CommandList_struct), 4349 hba[i]->nr_cmds * sizeof(CommandList_struct),
@@ -4456,16 +4461,7 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev)
4456 for (j = 0; j < hba[i]->nr_cmds; j++) 4461 for (j = 0; j < hba[i]->nr_cmds; j++)
4457 kfree(hba[i]->scatter_list[j]); 4462 kfree(hba[i]->scatter_list[j]);
4458 kfree(hba[i]->scatter_list); 4463 kfree(hba[i]->scatter_list);
4459 /* Only free up extra s/g lists if controller supports them */ 4464 cciss_free_sg_chain_blocks(hba[i]->cmd_sg_list, hba[i]->nr_cmds);
4460 if (hba[i]->chainsize > 0) {
4461 for (j = 0; j < hba[i]->nr_cmds; j++) {
4462 if (hba[i]->cmd_sg_list[j]) {
4463 kfree(hba[i]->cmd_sg_list[j]->sgchain);
4464 kfree(hba[i]->cmd_sg_list[j]);
4465 }
4466 }
4467 kfree(hba[i]->cmd_sg_list);
4468 }
4469 /* 4465 /*
4470 * Deliberately omit pci_disable_device(): it does something nasty to 4466 * Deliberately omit pci_disable_device(): it does something nasty to
4471 * Smart Array controllers that pci_enable_device does not undo 4467 * Smart Array controllers that pci_enable_device does not undo
@@ -4498,7 +4494,7 @@ static int __init cciss_init(void)
4498 * boundary. Given that we use pci_alloc_consistent() to allocate an 4494 * boundary. Given that we use pci_alloc_consistent() to allocate an
4499 * array of them, the size must be a multiple of 8 bytes. 4495 * array of them, the size must be a multiple of 8 bytes.
4500 */ 4496 */
4501 BUILD_BUG_ON(sizeof(CommandList_struct) % 8); 4497 BUILD_BUG_ON(sizeof(CommandList_struct) % COMMANDLIST_ALIGNMENT);
4502 4498
4503 printk(KERN_INFO DRIVER_NAME "\n"); 4499 printk(KERN_INFO DRIVER_NAME "\n");
4504 4500