diff options
Diffstat (limited to 'drivers/scsi/aacraid/aachba.c')
-rw-r--r-- | drivers/scsi/aacraid/aachba.c | 79 |
1 files changed, 53 insertions, 26 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 8e3493587299..83bfab73ff65 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c | |||
@@ -349,6 +349,27 @@ static void aac_io_done(struct scsi_cmnd * scsicmd) | |||
349 | spin_unlock_irqrestore(host->host_lock, cpu_flags); | 349 | spin_unlock_irqrestore(host->host_lock, cpu_flags); |
350 | } | 350 | } |
351 | 351 | ||
352 | static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len) | ||
353 | { | ||
354 | void *buf; | ||
355 | unsigned int transfer_len; | ||
356 | struct scatterlist *sg = scsicmd->request_buffer; | ||
357 | |||
358 | if (scsicmd->use_sg) { | ||
359 | buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; | ||
360 | transfer_len = min(sg->length, len + offset); | ||
361 | } else { | ||
362 | buf = scsicmd->request_buffer; | ||
363 | transfer_len = min(scsicmd->request_bufflen, len + offset); | ||
364 | } | ||
365 | |||
366 | memcpy(buf + offset, data, transfer_len - offset); | ||
367 | |||
368 | if (scsicmd->use_sg) | ||
369 | kunmap_atomic(buf - sg->offset, KM_IRQ0); | ||
370 | |||
371 | } | ||
372 | |||
352 | static void get_container_name_callback(void *context, struct fib * fibptr) | 373 | static void get_container_name_callback(void *context, struct fib * fibptr) |
353 | { | 374 | { |
354 | struct aac_get_name_resp * get_name_reply; | 375 | struct aac_get_name_resp * get_name_reply; |
@@ -364,18 +385,22 @@ static void get_container_name_callback(void *context, struct fib * fibptr) | |||
364 | /* Failure is irrelevant, using default value instead */ | 385 | /* Failure is irrelevant, using default value instead */ |
365 | if ((le32_to_cpu(get_name_reply->status) == CT_OK) | 386 | if ((le32_to_cpu(get_name_reply->status) == CT_OK) |
366 | && (get_name_reply->data[0] != '\0')) { | 387 | && (get_name_reply->data[0] != '\0')) { |
367 | int count; | 388 | char *sp = get_name_reply->data; |
368 | char * dp; | ||
369 | char * sp = get_name_reply->data; | ||
370 | sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0'; | 389 | sp[sizeof(((struct aac_get_name_resp *)NULL)->data)-1] = '\0'; |
371 | while (*sp == ' ') | 390 | while (*sp == ' ') |
372 | ++sp; | 391 | ++sp; |
373 | count = sizeof(((struct inquiry_data *)NULL)->inqd_pid); | 392 | if (*sp) { |
374 | dp = ((struct inquiry_data *)scsicmd->request_buffer)->inqd_pid; | 393 | char d[sizeof(((struct inquiry_data *)NULL)->inqd_pid)]; |
375 | if (*sp) do { | 394 | int count = sizeof(d); |
376 | *dp++ = (*sp) ? *sp++ : ' '; | 395 | char *dp = d; |
377 | } while (--count > 0); | 396 | do { |
397 | *dp++ = (*sp) ? *sp++ : ' '; | ||
398 | } while (--count > 0); | ||
399 | aac_internal_transfer(scsicmd, d, | ||
400 | offsetof(struct inquiry_data, inqd_pid), sizeof(d)); | ||
401 | } | ||
378 | } | 402 | } |
403 | |||
379 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 404 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
380 | 405 | ||
381 | fib_complete(fibptr); | 406 | fib_complete(fibptr); |
@@ -1344,44 +1369,45 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1344 | switch (scsicmd->cmnd[0]) { | 1369 | switch (scsicmd->cmnd[0]) { |
1345 | case INQUIRY: | 1370 | case INQUIRY: |
1346 | { | 1371 | { |
1347 | struct inquiry_data *inq_data_ptr; | 1372 | struct inquiry_data inq_data; |
1348 | 1373 | ||
1349 | dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id)); | 1374 | dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->device->id)); |
1350 | inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer; | 1375 | memset(&inq_data, 0, sizeof (struct inquiry_data)); |
1351 | memset(inq_data_ptr, 0, sizeof (struct inquiry_data)); | ||
1352 | 1376 | ||
1353 | inq_data_ptr->inqd_ver = 2; /* claim compliance to SCSI-2 */ | 1377 | inq_data.inqd_ver = 2; /* claim compliance to SCSI-2 */ |
1354 | inq_data_ptr->inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */ | 1378 | inq_data.inqd_dtq = 0x80; /* set RMB bit to one indicating that the medium is removable */ |
1355 | inq_data_ptr->inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ | 1379 | inq_data.inqd_rdf = 2; /* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */ |
1356 | inq_data_ptr->inqd_len = 31; | 1380 | inq_data.inqd_len = 31; |
1357 | /*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ | 1381 | /*Format for "pad2" is RelAdr | WBus32 | WBus16 | Sync | Linked |Reserved| CmdQue | SftRe */ |
1358 | inq_data_ptr->inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */ | 1382 | inq_data.inqd_pad2= 0x32 ; /*WBus16|Sync|CmdQue */ |
1359 | /* | 1383 | /* |
1360 | * Set the Vendor, Product, and Revision Level | 1384 | * Set the Vendor, Product, and Revision Level |
1361 | * see: <vendor>.c i.e. aac.c | 1385 | * see: <vendor>.c i.e. aac.c |
1362 | */ | 1386 | */ |
1363 | if (scsicmd->device->id == host->this_id) { | 1387 | if (scsicmd->device->id == host->this_id) { |
1364 | setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), (sizeof(container_types)/sizeof(char *))); | 1388 | setinqstr(cardtype, (void *) (inq_data.inqd_vid), (sizeof(container_types)/sizeof(char *))); |
1365 | inq_data_ptr->inqd_pdt = INQD_PDT_PROC; /* Processor device */ | 1389 | inq_data.inqd_pdt = INQD_PDT_PROC; /* Processor device */ |
1390 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); | ||
1366 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1391 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
1367 | scsicmd->scsi_done(scsicmd); | 1392 | scsicmd->scsi_done(scsicmd); |
1368 | return 0; | 1393 | return 0; |
1369 | } | 1394 | } |
1370 | setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr[cid].type); | 1395 | setinqstr(cardtype, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type); |
1371 | inq_data_ptr->inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ | 1396 | inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */ |
1397 | aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data)); | ||
1372 | return aac_get_container_name(scsicmd, cid); | 1398 | return aac_get_container_name(scsicmd, cid); |
1373 | } | 1399 | } |
1374 | case READ_CAPACITY: | 1400 | case READ_CAPACITY: |
1375 | { | 1401 | { |
1376 | u32 capacity; | 1402 | u32 capacity; |
1377 | char *cp; | 1403 | char cp[8]; |
1378 | 1404 | ||
1379 | dprintk((KERN_DEBUG "READ CAPACITY command.\n")); | 1405 | dprintk((KERN_DEBUG "READ CAPACITY command.\n")); |
1380 | if (fsa_dev_ptr[cid].size <= 0x100000000LL) | 1406 | if (fsa_dev_ptr[cid].size <= 0x100000000LL) |
1381 | capacity = fsa_dev_ptr[cid].size - 1; | 1407 | capacity = fsa_dev_ptr[cid].size - 1; |
1382 | else | 1408 | else |
1383 | capacity = (u32)-1; | 1409 | capacity = (u32)-1; |
1384 | cp = scsicmd->request_buffer; | 1410 | |
1385 | cp[0] = (capacity >> 24) & 0xff; | 1411 | cp[0] = (capacity >> 24) & 0xff; |
1386 | cp[1] = (capacity >> 16) & 0xff; | 1412 | cp[1] = (capacity >> 16) & 0xff; |
1387 | cp[2] = (capacity >> 8) & 0xff; | 1413 | cp[2] = (capacity >> 8) & 0xff; |
@@ -1390,6 +1416,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1390 | cp[5] = 0; | 1416 | cp[5] = 0; |
1391 | cp[6] = 2; | 1417 | cp[6] = 2; |
1392 | cp[7] = 0; | 1418 | cp[7] = 0; |
1419 | aac_internal_transfer(scsicmd, cp, 0, sizeof(cp)); | ||
1393 | 1420 | ||
1394 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1421 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
1395 | scsicmd->scsi_done(scsicmd); | 1422 | scsicmd->scsi_done(scsicmd); |
@@ -1399,15 +1426,15 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1399 | 1426 | ||
1400 | case MODE_SENSE: | 1427 | case MODE_SENSE: |
1401 | { | 1428 | { |
1402 | char *mode_buf; | 1429 | char mode_buf[4]; |
1403 | 1430 | ||
1404 | dprintk((KERN_DEBUG "MODE SENSE command.\n")); | 1431 | dprintk((KERN_DEBUG "MODE SENSE command.\n")); |
1405 | mode_buf = scsicmd->request_buffer; | ||
1406 | mode_buf[0] = 3; /* Mode data length */ | 1432 | mode_buf[0] = 3; /* Mode data length */ |
1407 | mode_buf[1] = 0; /* Medium type - default */ | 1433 | mode_buf[1] = 0; /* Medium type - default */ |
1408 | mode_buf[2] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ | 1434 | mode_buf[2] = 0; /* Device-specific param, bit 8: 0/1 = write enabled/protected */ |
1409 | mode_buf[3] = 0; /* Block descriptor length */ | 1435 | mode_buf[3] = 0; /* Block descriptor length */ |
1410 | 1436 | ||
1437 | aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf)); | ||
1411 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1438 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
1412 | scsicmd->scsi_done(scsicmd); | 1439 | scsicmd->scsi_done(scsicmd); |
1413 | 1440 | ||
@@ -1415,10 +1442,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1415 | } | 1442 | } |
1416 | case MODE_SENSE_10: | 1443 | case MODE_SENSE_10: |
1417 | { | 1444 | { |
1418 | char *mode_buf; | 1445 | char mode_buf[8]; |
1419 | 1446 | ||
1420 | dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n")); | 1447 | dprintk((KERN_DEBUG "MODE SENSE 10 byte command.\n")); |
1421 | mode_buf = scsicmd->request_buffer; | ||
1422 | mode_buf[0] = 0; /* Mode data length (MSB) */ | 1448 | mode_buf[0] = 0; /* Mode data length (MSB) */ |
1423 | mode_buf[1] = 6; /* Mode data length (LSB) */ | 1449 | mode_buf[1] = 6; /* Mode data length (LSB) */ |
1424 | mode_buf[2] = 0; /* Medium type - default */ | 1450 | mode_buf[2] = 0; /* Medium type - default */ |
@@ -1427,6 +1453,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd) | |||
1427 | mode_buf[5] = 0; /* reserved */ | 1453 | mode_buf[5] = 0; /* reserved */ |
1428 | mode_buf[6] = 0; /* Block descriptor length (MSB) */ | 1454 | mode_buf[6] = 0; /* Block descriptor length (MSB) */ |
1429 | mode_buf[7] = 0; /* Block descriptor length (LSB) */ | 1455 | mode_buf[7] = 0; /* Block descriptor length (LSB) */ |
1456 | aac_internal_transfer(scsicmd, mode_buf, 0, sizeof(mode_buf)); | ||
1430 | 1457 | ||
1431 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; | 1458 | scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD; |
1432 | scsicmd->scsi_done(scsicmd); | 1459 | scsicmd->scsi_done(scsicmd); |