Files
@ bd21c8aa7237
Branch filter:
Location: vmkdrivers/vmkdrivers/src_9/drivers/scsi/adp94xx/adp94xx_osm.h
bd21c8aa7237
39.0 KiB
text/x-chdr
ESXi-6.0.0b
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 | /*
* Adaptec ADP94xx SAS HBA device driver for Linux.
*
* Written by : David Chaw <david_chaw@adaptec.com>
*
* Copyright (c) 2004 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the "NO WARRANTY" disclaimer below
* ("Disclaimer") and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution.
* 3. Neither the names of the above-listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
* GNU General Public License ("GPL") version 2 as published by the Free
* Software Foundation.
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES.
*
* $Id: //depot/razor/linux/src/adp94xx_osm.h#159 $
*
*/
#ifndef ADP94XX_OSM_H
#define ADP94XX_OSM_H
#include <asm/byteorder.h>
#if !defined(__VMKLNX__)
#include <asm/io.h>
#endif /* !defined(__VMKLNX__) */
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/pci.h>
#include <linux/smp_lock.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#if !defined(__VMKLNX__)
#include <linux/config.h>
#endif /* !defined(__VMKLNX__) */
#include <linux/slab.h>
#if !defined(__VMKLNX__)
#include <linux/nmi.h>
#endif /* !defined(__VMKLNX__) */
#include <linux/hdreg.h>
#include <asm/uaccess.h>
#include <linux/ioctl.h>
#include <linux/init.h>
#if defined(__VMKLNX__)
#include <asm/io.h>
#endif /* defined(__VMKLNX__) */
#ifndef KERNEL_VERSION
#define KERNEL_VERSION(x,y,z) (((x)<<16) + ((y)<<8) + (z))
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
#include <linux/blk.h>
#include "sd.h"
#include "hosts.h"
#include "scsi.h"
#else
#include <linux/moduleparam.h>
#include <scsi/scsi_host.h>
#if !defined(__VMKLNX__)
#include <scsi/scsi_driver.h>
#endif /* !defined(__VMKLNX__) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
#include <scsi/scsi_request.h>
#endif
#include <scsi/scsi.h>
#include <scsi/scsi_eh.h>
#include <scsi/scsi_tcq.h>
#include <scsi/scsi_device.h>
#include <scsi/scsi_cmnd.h>
#include <scsi/scsicam.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)
#if !defined(__VMKLNX__)
#include "scsi_priv.h"
#endif /* !defined(__VMKLNX__) */
#endif
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
typedef struct scsi_cmnd Scsi_Cmnd;
typedef struct scsi_device Scsi_Device;
typedef struct scsi_request Scsi_Request;
typedef struct scsi_host_template Scsi_Host_Template;
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef SCSI_DATA_READ
#define SCSI_DATA_READ DMA_FROM_DEVICE
#define SCSI_DATA_WRITE DMA_TO_DEVICE
#define SCSI_DATA_UNKNOWN DMA_BIDIRECTIONAL
#define SCSI_DATA_NONE DMA_NONE
#define scsi_to_pci_dma_dir(_a) (_a)
#endif
#include <linux/blkdev.h>
#define __packed __attribute__ ((packed))
/* Driver name */
#define ASD_DRIVER_NAME "adp94xx"
#define ASD_DRIVER_DESCRIPTION "Adaptec Linux SAS/SATA Family Driver"
#define ASD_MAJOR_VERSION 1
#define ASD_MINOR_VERSION 0
#ifdef SEQUENCER_UPDATE
#define ASD_BUILD_VERSION 8
#define ASD_RELEASE_VERSION 12
#define ASD_DRIVER_VERSION "1.0.8.12-6vmw"
#else
#define ASD_BUILD_VERSION 7
#define ASD_RELEASE_VERSION 5
#define ASD_DRIVER_VERSION "1.0.7"
#endif
/* For now, let's limit ourselves on kernel 2.4, 2.6 and greater */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
#error "This driver only support kernel 2.4 or greater"
#endif
/************************* Forward Declarations *******************************/
struct asd_softc;
struct asd_port;
struct scb;
struct asd_scb_platform_data;
struct asd_domain;
struct asd_done_list;
/********************* Definitions Required by the Core ***********************/
/*
* Number of SG segments we require. So long as the S/G segments for
* a particular transaction are allocated in a physically contiguous
* manner, the number of S/G segments is unrestricted.
*/
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
/*
* We dynamically adjust the number of segments in pre-2.5 kernels to
* avoid fragmentation issues in the SCSI mid-layer's private memory
* allocator. See adp94xx_osm.c asd_size_nseg() for details.
*/
extern u_int asd_nseg;
#define ASD_NSEG asd_nseg
#define ASD_LINUX_MIN_NSEG 64
#else
#define ASD_NSEG 128
#endif
/* Constants definition */
#define ASD_MAX_QUEUE ASD_MAX_ALLOCATED_SCBS
/*
* DC: Does MAX_SECTORS 255 works for some SATA drives ?
* Preferable set it to 255 for better performance in 2.6 kernel.
* In 2.4 kernel, it seems that block layer always limited to 64 sectors.
*/
//#define ASD_MAX_SECTORS 8192
#define ASD_MAX_SECTORS 128
#define ASD_MAX_IO_HANDLES 6
/* Device mapping definition */
/*
* XXX This should really be limited by SAS/SAM. With
* the use of hash tables in the domain and target
* structures as well as DDB site recycling, we
* should have no limit.
*/
#define ASD_MAX_LUNS 128
#define SAS_LUN_LEN 8
/********************************** Misc Macros *******************************/
#ifndef roundup
#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
#endif
static inline uint32_t
roundup_pow2(uint32_t val)
{
val--;
val |= val >> 1;
val |= val >> 2;
val |= val >> 4;
val |= val >> 8;
val |= val >> 16;
return (val + 1);
}
#ifndef powerof2
#define powerof2(x) ((((x)-1)&(x))==0)
#endif
#ifndef MAX
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
#endif
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(*array))
/******************************* Byte Order ***********************************/
#define asd_htobe16(x) cpu_to_be16(x)
#define asd_htobe32(x) cpu_to_be32(x)
#define asd_htobe64(x) cpu_to_be64(x)
#define asd_htole16(x) cpu_to_le16(x)
#define asd_htole32(x) cpu_to_le32(x)
#define asd_htole64(x) cpu_to_le64(x)
#define asd_be16toh(x) be16_to_cpu(x)
#define asd_be32toh(x) be32_to_cpu(x)
#define asd_be64toh(x) be64_to_cpu(x)
#define asd_le16toh(x) le16_to_cpu(x)
#define asd_le32toh(x) le32_to_cpu(x)
#define asd_le64toh(x) le64_to_cpu(x)
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234
#endif
#ifndef BIG_ENDIAN
#define BIG_ENDIAN 4321
#endif
#ifndef BYTE_ORDER
#if defined(__BIG_ENDIAN)
#define BYTE_ORDER BIG_ENDIAN
#endif
#if defined(__LITTLE_ENDIAN)
#define BYTE_ORDER LITTLE_ENDIAN
#endif
#endif /* BYTE_ORDER */
/***************************** Bus Space/DMA **********************************/
struct asd_dma_tag
{
uint32_t alignment;
uint32_t maxsize;
};
typedef struct asd_dma_tag *bus_dma_tag_t;
struct asd_dmamap
{
dma_addr_t bus_addr;
};
typedef struct asd_dmamap * bus_dmamap_t;
/*
* Data structure used to track a slab of DMA
* safe memory.
*/
struct map_node {
bus_dmamap_t dmamap;
dma_addr_t busaddr;
uint8_t *vaddr;
struct list_head links;
};
int asd_dma_tag_create(struct asd_softc *, uint32_t /*alignment*/,
uint32_t /*maxsize*/, int /*flags*/,
bus_dma_tag_t * /*dma_tagp*/);
void asd_dma_tag_destroy(struct asd_softc *, bus_dma_tag_t /*tag*/);
int asd_dmamem_alloc(struct asd_softc *, bus_dma_tag_t /*dmat*/,
void** /*vaddr*/, int /*flags*/,
bus_dmamap_t * /*mapp*/, dma_addr_t * /*baddr*/);
void asd_dmamem_free(struct asd_softc *, bus_dma_tag_t /*dmat*/,
void* /*vaddr*/, bus_dmamap_t /*map*/);
void asd_dmamap_destroy(struct asd_softc *, bus_dma_tag_t /*tag*/,
bus_dmamap_t /*map*/);
int asd_alloc_dma_mem(struct asd_softc *, unsigned, void **,
dma_addr_t *, bus_dma_tag_t *, struct map_node *);
void asd_free_dma_mem(struct asd_softc *, bus_dma_tag_t, struct map_node *);
/* IOCTL registration wrappers */
int asd_register_ioctl_dev(void);
int asd_unregister_ioctl_dev(void);
int asd_ctl_init_internal_data(struct asd_softc *asd);
struct asd_softc * asd_get_softc_by_hba_index(uint32_t hba_index);
int asd_get_number_of_hbas_present(void);
struct asd_target *
asd_get_os_target_from_port(struct asd_softc *asd,
struct asd_port *port,
struct asd_domain *dm);
struct asd_device *
asd_get_device_from_lun(struct asd_softc *asd,
struct asd_target *targ, uint8_t *saslun);
int asd_get_os_platform_map_from_sasaddr(struct asd_softc *asd,
struct asd_port *port,
uint8_t *sasaddr, uint8_t *saslun,
uint8_t *host, uint8_t *bus,
uint8_t *target, uint8_t *lun);
struct asd_port *
asd_get_sas_addr_from_platform_map(struct asd_softc *asd,
uint8_t host, uint8_t bus,
uint8_t target, uint8_t lun,
uint8_t *sasaddr, uint8_t *saslun);
struct asd_target *
asd_get_sas_target_from_sasaddr(struct asd_softc *asd,
struct asd_port *port,
uint8_t *sasaddr);
struct asd_target *
asd_get_os_target_from_sasaddr(struct asd_softc *asd,
struct asd_domain *dm,
uint8_t *sasddr);
struct scb *
asd_find_pending_scb_by_qtag(struct asd_softc *asd, uint32_t qtag);
int asd_hwi_check_cmd_pending(struct asd_softc *asd, struct scb *scb,
struct asd_done_list *dl);
/* indicates that the scsi_cmnd is generated by CSMI */
#define ASD_CSMI_COMMAND 0xfaceface
#if (BITS_PER_LONG > 32) || \
(defined CONFIG_HIGHMEM64G && defined CONFIG_HIGHIO)
#define ASD_DMA_64BIT_SUPPORT 1
#else
#define ASD_DMA_64BIT_SUPPORT 0
#endif
/*************************** Linux DMA Wrappers *******************************/
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#define asd_alloc_coherent(asd, size, bus_addr_ptr) \
dma_alloc_coherent(asd->dev, size, bus_addr_ptr, /*flag*/0)
#define asd_free_coherent(asd, size, vaddr, bus_addr) \
dma_free_coherent(asd->dev, size, vaddr, bus_addr)
#define asd_map_single(asd, buf, size, direction) \
dma_map_single(asd->dev, buf, size, direction)
#define asd_unmap_single(asd, busaddr, size, direction) \
dma_unmap_single(asd->dev, busaddr, size, direction)
#define asd_map_sg(asd, sg_list, num_sg, direction) \
dma_map_sg(asd->dev, sg_list, num_sg, direction)
#define asd_unmap_sg(asd, sg_list, num_sg, direction) \
dma_unmap_sg(asd->dev, sg_list, num_sg, direction)
#else /* LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) */
#define asd_alloc_coherent(asd, size, bus_addr_ptr) \
pci_alloc_consistent(asd->dev, size, bus_addr_ptr)
#define asd_free_coherent(asd, size, vaddr, bus_addr) \
pci_free_consistent(asd->dev, size, vaddr, bus_addr)
#define asd_map_single(asd, buf, size, direction) \
pci_map_single(asd->dev, buf, size, direction)
#define asd_unmap_single(asd, busaddr, size, direction) \
pci_unmap_single(asd->dev, busaddr, size, direction)
#define asd_map_sg(asd, sg_list, num_sg, direction) \
pci_map_sg(asd->dev, sg_list, num_sg, direction)
#define asd_unmap_sg(asd, sg_list, num_sg, direction) \
pci_unmap_sg(asd->dev, sg_list, num_sg, direction)
#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2,4,0) */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#define asd_set_dma_mask(asd, mask) dma_set_mask(asd->dev, mask)
#define asd_set_consistent_dma_mask(asd, mask) \
pci_set_consistent_dma_mask(asd_dev_to_pdev(asd->dev), mask)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,3)
/*
* Device softc is NULL for EISA devices.
*/
#define asd_set_dma_mask(asd, mask) \
((asd)->dev == NULL ? 0 : pci_set_dma_mask(asd->dev, mask))
/* Always successfull in 2.4.X kernels */
#define asd_set_consistent_dma_mask(asd, mask) (0)
#else
/*
* Device softc is NULL for EISA devices.
* Always "return" 0 for success.
*/
#define asd_set_dma_mask(asd, mask) \
(((asd)->dev == NULL) \
? 0 \
: (((asd)->dev->dma_mask = mask) && 0))
/* Always successfull in 2.4.X kernels */
#define asd_set_consistent_dma_mask(asd, mask) (0)
#endif
/* Forward compatibility */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
typedef struct device *asd_dev_t;
#else
typedef struct pci_dev *asd_dev_t;
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#define asd_dev_to_pdev(dev) to_pci_dev(dev)
#define asd_pdev_to_dev(pdev) (&pdev->dev)
#else
#define asd_dev_to_pdev(dev) (dev)
#define asd_pdev_to_dev(pdev) (pdev)
#endif
#define asd_pci_dev(asd) asd_dev_to_pdev((asd)->dev)
#define ASD_GET_PADR(addr) ((uint32_t) (addr))
#if (BITS_PER_LONG > 32)
#define ASD_GET_PUADR(addr) ((uint32_t) ((addr) >> 32))
#else
#define ASD_GET_PUADR(addr) ((uint32_t) (0))
#endif
typedef enum {
ASD_SCB_UP_EH_SEM = 0x01,
ASD_TIMEOUT_ACTIVE = 0x02,
ASD_RELEASE_SIMQ = 0x04,
} asd_scb_flags;
/**************************** Front End Queues ********************************/
/*
* Data structure used to cast the Linux struct scsi_cmnd to something
* that allows us to use the queue macros. The linux structure has
* plenty of space to hold the links fields as required by the queue
* macros, but the queue macors require them to have the correct type.
*/
struct asd_cmd_internal {
/* Area owned by the Linux scsi layer. */
uint8_t private[__builtin_offsetof(struct scsi_cmnd, SCp.Status)];
struct list_head links;
uint32_t end;
};
union asd_cmd {
struct asd_cmd_internal icmd;
struct scsi_cmnd scsi_cmd;
};
#define acmd_icmd(cmd) ((cmd)->icmd)
#define acmd_scsi_cmd(cmd) ((cmd)->scsi_cmd)
#define acmd_links icmd.links
/************************** Razor Architecture Layers ************************/
/*
* The following typedefs define the protocols for each layer of the Razor
* architecture.
*/
/*
* The Command Set layer consists of everything having to do with the type
* of command that is sent to the target.
*/
typedef enum {
ASD_COMMAND_SET_UNKNOWN,
ASD_COMMAND_SET_SCSI,
ASD_COMMAND_SET_ATA,
ASD_COMMAND_SET_ATAPI,
ASD_COMMAND_SET_SMP,
ASD_COMMAND_SET_BAD
} COMMAND_SET_TYPE;
/*
* The Device Protocol layer are things that are specific to a device,
* regardless of which command set is used. For example, a device using
* ASD_DEVICE_PROTOCOL_ATA might use the command set ASD_COMMAND_SET_ATA or
* ASD_COMMAND_SET_ATAPI.
*/
typedef enum {
ASD_DEVICE_PROTOCOL_UNKNOWN,
ASD_DEVICE_PROTOCOL_SCSI,
ASD_DEVICE_PROTOCOL_ATA,
ASD_DEVICE_PROTOCOL_SMP
} DEVICE_PROTOCOL_TYPE;
/*
* The transport layer can be thought of as the frame which is used to send
* to a device of type DEVICE_PROTOCOL that supports the COMMAND_SET_TYPE
* command set.
*/
typedef enum {
ASD_TRANSPORT_UNKNOWN,
ASD_TRANSPORT_SSP,
ASD_TRANSPORT_SMP,
ASD_TRANSPORT_STP,
ASD_TRANSPORT_ATA
} TRANSPORT_TYPE;
/*
* The management layer deals with issues of routing.
*/
typedef enum {
ASD_DEVICE_NONE,
ASD_DEVICE_FANOUT_EXPANDER,
ASD_DEVICE_EDGE_EXPANDER,
ASD_DEVICE_END,
ASD_DEVICE_UNKNOWN
} MANAGEMENT_TYPE;
/*
* The link layer refers to the link that is connected to the initiator.
*/
typedef enum {
ASD_LINK_UNKNOWN,
ASD_LINK_SAS,
ASD_LINK_SATA,
ASD_LINK_GPIO,
ASD_LINK_I2C
} LINK_TYPE;
typedef union asd_cmd *asd_io_ctx_t;
/* Discovery include file */
#include "adp94xx_discover.h"
/* HWI include file */
#include "adp94xx_hwi.h"
/*************************** Device Data Structures ***************************/
/*
* A per probed device structure used to deal with some error recovery
* scenarios that the Linux mid-layer code just doesn't know how to
* handle. The structure allocated for a device only becomes persistent
* after a successfully completed inquiry command to the target when
* that inquiry data indicates a lun is present.
*/
typedef enum {
ASD_DEV_UNCONFIGURED = 0x0001,
ASD_DEV_FREEZE_TIL_EMPTY = 0x0002, /* Freeze until active is empty */
ASD_DEV_TIMER_ACTIVE = 0x0004, /* Our timer is active */
ASD_DEV_ON_RUN_LIST = 0x0008, /* Queued to be run later */
ASD_DEV_Q_BASIC = 0x0010, /* Allow basic device queuing */
ASD_DEV_Q_TAGGED = 0x0020, /* Allow full SCSI2 cmd queueing */
ASD_DEV_SLAVE_CONFIGURED = 0x0040, /* Device has been configured. */
ASD_DEV_DESTROY_WAS_ACTIVE = 0x0080, /* Device has active IO(s) when
the ITNL timer expired. */
ASD_DEV_DPC_ACTIVE = 0x0100 /* There is an active DPC task,*/
} asd_dev_flags;
struct asd_target;
struct asd_device {
struct list_head links;
struct list_head busyq;
/*
* The number of transactions currently queued to the device.
*/
int active;
/*
* The currently allowed number of transactions that can be queued to
* the device. Must be signed for conversion from tagged to untagged
* mode where the device may have more than one outstanding active
* transaction.
*/
int openings;
/*
* A positive count indicates that this device's queue is halted.
*/
u_int qfrozen;
/*
* Cumulative command counter.
*/
u_long commands_issued;
/*
* The number of tagged transactions when running at our current
* opening level that have been successfully received by this
* device since the last QUEUE FULL.
*/
u_int tag_success_count;
#define ASD_TAG_SUCCESS_INTERVAL 50
asd_dev_flags flags;
/*
* Per device timer and task.
*/
struct timer_list timer;
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,41)
struct tq_struct taskq;
#else
struct work_struct workq;
#endif
/*
* The high limit for the tags variable.
*/
u_int maxtags;
/*
* The computed number of tags outstanding
* at the time of the last QUEUE FULL event.
*/
u_int tags_on_last_queuefull;
/*
* How many times we have seen a queue full with the same
* number of tags. This is used to stop our adaptive queue depth
* algorithm on devices with a fixed number of tags.
*/
u_int last_queuefull_same_count;
#define ASD_LOCK_TAGS_COUNT 50
/*
* Device mapping path for the OS.
* This is a duplicate of info in scsi_device and
* should be discarded soon.
*/
u_int ch;
u_int id;
u_int lun;
uint8_t saslun[SAS_LUN_LEN];
Scsi_Device *scsi_device;
struct asd_target *target;
#ifdef MULTIPATH_IO
struct asd_target *current_target;
#endif
};
typedef enum {
ASD_TARG_FLAGS_NONE = 0x0000,
ASD_TARG_IN_RECOVERY = 0x0001,
ASD_TARG_ONLINE = 0x0002,
ASD_TARG_RESEEN = 0x0004,
ASD_TARG_HOT_REMOVED = 0x0008,
ASD_TARG_HOT_ADDED = 0x0010,
ASD_TARG_NEEDS_MAP = 0x0020,
ASD_TARG_MAPPED = 0x0040,
ASD_TARG_MAP_BOOT = 0x0080
} asd_targ_flags;
/*
* Contains pertinent fields needed to generete a hardware DDB.
*/
struct asd_ddb_data {
uint8_t sas_addr[SAS_ADDR_LEN];
uint8_t hashed_sas_addr[HASHED_SAS_ADDR_LEN];
uint8_t conn_rate;
uint16_t itnl_const;
/* Index to DDB entry. */
uint16_t conn_handle;
uint16_t sister_ddb;
/*
* Indicates whether the device port protocol is SSP, STP, SMP,
* SATA direct attched or SATA Port Multi. This will be used when
* setting value for OPEN field.
*/
uint8_t attr;
/*
* OPEN bit will be set if the device port is connected by
* SSP, STP or SMP. In addition for STP, SUPPORT AFFILIATION and
* STP AFFLIATION policy need to be set.
* Otherwise, for SATA direct attached or SATA Port Multi, OPEN bit
* shall not be set.
*/
uint8_t open_affl;
/*
* Initial FIS status.
*/
uint8_t sata_status;
};
#define FIS_LENGTH 20
/*
* Defines for the features_state member
*/
#define SATA_USES_DMA 0x0001
#define SATA_USES_48BIT 0x0002
#define SATA_USES_QUEUEING 0x0004
#define SATA_USES_WRITE_FUA 0x0008
#define SATA_USES_REMOVABLE 0x0010
#define SATA_USES_WRITE_BUFFER 0x0020
#define SATA_USES_READ_BUFFER 0x0040
#define SATA_USES_WRITE_CACHE 0x0080
#define SATA_USES_READ_AHEAD 0x0100
#define SATA_USES_SMART 0x0200
#define SATA_USES_UDMA 0x0400
/*
* Defines for the features_enabled member (to store capability)
*/
#define WRITE_CACHE_FEATURE_ENABLED 0x0001
#define READ_AHEAD_FEATURE_ENABLED 0x0002
#define SMART_FEATURE_ENABLED 0x0004
#define NEEDS_XFER_SETFEATURES 0x0008
int
asd_sata_identify_build(
struct asd_softc *asd,
struct asd_target *target,
struct scb *scb
);
// ----------------------------------------------------------------------------
/*
* For devices supporting the SCSI command set
*/
struct asd_scsi_command_set {
unsigned num_luns;
uint32_t flags;
uint64_t *luns;
uint8_t *ident;
unsigned ident_len;
uint8_t *inquiry;
};
struct asd_smp_command_set {
struct SMPResponseReportManufacturerInfo
manufacturer_info;
};
/*
* For devices supporting the ATA command set
*/
struct asd_ata_command_set {
/*
* There are a few differences in the structures for the data that
* is returned by IDENTIFY and PACKET IDENTIFY. We are using the
* same structure for both ATA and ATAPI.
*/
struct hd_driveid adp_hd_driveid;
/*
* These members are in the command set structure because they are
* deriviced by, or control features and functions specified in the
* adp_hd_driveid struture.
*/
unsigned features_state;
unsigned features_enabled;
unsigned dma_mode_level;
};
/*
* For devices supporting the ATAPI command set
*/
struct asd_atapi_command_set {
/*
* There are a few differences in the structures for the data that
* is returned by IDENTIFY and PACKET IDENTIFY. We are using the
* same structure for both ATA and ATAPI.
*/
struct hd_driveid adp_hd_driveid;
/*
* These members are in the command set structure because they are
* deriviced by, or control features and functions specified in the
* adp_hd_driveid struture.
*/
unsigned features_state;
unsigned features_enabled;
unsigned dma_mode_level;
};
/*
* These are members that are specific to a specific type of command set.
*/
union asd_command_set {
struct asd_scsi_command_set scsi_command_set;
struct asd_ata_command_set ata_command_set;
struct asd_atapi_command_set atapi_command_set;
struct asd_smp_command_set smp_command_set;
};
#define ata_cmdset command_set.ata_command_set
#define scsi_cmdset command_set.scsi_command_set
#define atapi_cmdset command_set.atapi_command_set
#define smp_cmdset command_set.smp_command_set
// ----------------------------------------------------------------------------
struct asd_ata_device_protocol {
uint8_t initial_fis[FIS_LENGTH];
};
union asd_device_protocol {
struct asd_ata_device_protocol ata_device_protocol;
};
/*
* Defines for the menagement_flags member
*/
#define DEVICE_SET_ROOT 0x0001
struct asd_target {
/*
* A positive count indicates that this
* target's queue is halted.
*/
u_int qfrozen;
/*
* XXX Use hash table for sparse 8byte lun support???
*/
struct asd_device *devices[ASD_MAX_LUNS];
u_int target_id;
int refcount;
struct asd_softc *softc;
asd_targ_flags flags;
struct asd_domain *domain;
/*
* Per target timer.
*/
struct timer_list timer;
/*
* Command Set Layer (SCSI, ATAPI, ATA, SMP)
* --------------------------------------------------------
*/
COMMAND_SET_TYPE command_set_type;
union asd_command_set command_set;
/*
* Device Protocol Layer (SCSI, ATA, SMP)
* --------------------------------------------------------
*/
DEVICE_PROTOCOL_TYPE device_protocol_type;
union asd_device_protocol device_protocol;
/*
* Transport Layer (SSP, SMP, STP, FIS)
* --------------------------------------------------------
*/
TRANSPORT_TYPE transport_type;
/*
* Management Layer (DIRECT, EXPANDER, FANOUT)
* --------------------------------------------------------
*/
MANAGEMENT_TYPE management_type;
unsigned num_phys;
unsigned num_route_indexes;
unsigned configurable_route_table;
uint16_t *route_indexes;
struct SMPResponseDiscover *Phy;
uint8_t *RouteTable;
uint32_t management_flags;
/*
* Our parent SAS device (e.g. expander)
* in this SAS domain.
*/
struct asd_target *parent;
/*
* Our children SAS devices (if not end device)
* in this SAS domain.
*/
struct list_head children;
/*
* List of targets that are connected to a parent
* expander (children)
*/
struct list_head siblings;
/*
* List links for chaining together all targets
* in this SAS domain on to the port object.
*/
struct list_head all_domain_targets;
/*
* List links of targets that need to be validated
* because they have been hot-added or hot-removed.
*/
struct list_head validate_links;
/*
* List links of target structures that map to the
* same physical sevice.
*/
struct list_head multipath;
/*
* Link Layer (SAS, SATA, GPIO, I2C)
* --------------------------------------------------------
*/
LINK_TYPE link_type;
struct asd_ddb_data ddb_profile;
/*
* Controller port used to route to
* this device.
*/
struct asd_port *src_port;
};
struct asd_domain {
/*
* XXX Use Hash table to support
* large/sparse target configurations.
*/
struct asd_target *targets[ASD_MAX_TARGET_IDS];
u_int channel_mapping;
u_int refcount;
};
typedef enum {
ASD_DISCOVERY_ACTIVE = 0x01,
ASD_DISCOVERY_INIT = 0x02,
ASD_DISCOVERY_SHUTDOWN = 0x04,
ASD_RECOVERY_SHUTDOWN = 0x08,
#ifdef ASD_EH_SIMULATION
ASD_EH_SIMUL_SHUTDOWN = 0x10
#endif
} asd_platform_flags;
struct asd_scb_platform_data {
struct asd_target *targ;
struct asd_device *dev;
asd_scb_flags flags;
dma_addr_t buf_busaddr;
/*
* Timeout timer tick, used to timeout internal cmd that is
* sent to the sequencer or target.
*/
struct timer_list timeout;
};
struct asd_platform_data {
spinlock_t spinlock;
struct Scsi_Host *scsi_host;
/*
* Channel to Domain Mapping.
*/
struct asd_domain **domains;
u_int num_domains;
/*
* Queued device I/O scheduling support.
*/
struct list_head pending_os_scbs;
struct list_head device_runq;
struct tasklet_struct runq_tasklet;
struct tasklet_struct unblock_tasklet;
u_int qfrozen;
/*
* Completion Ordering Queue.
*/
struct list_head completeq;
/*
* LRU target DDB ageing queue. Used to
* select candidates for DDB recycling.
* LFU would be a better scheme and could
* be achieved in O(logN) using a heap
* queue, but keep this simple for now.
*/
struct list_head lru_ddb_q;
/*
* Discovery Thread Support.
*/
pid_t discovery_pid;
struct semaphore discovery_sem;
struct semaphore discovery_ending_sem;
/*
* Error Recovery Thread Support.
*/
pid_t ehandler_pid;
struct semaphore ehandler_sem;
struct semaphore ehandler_ending_sem;
#ifdef ASD_EH_SIMULATION
/*
* EH Recovery Simulation thread.
*/
pid_t eh_simul_pid;
struct semaphore eh_simul_sem;
#endif
/*
* Wait Queue.
*/
wait_queue_head_t waitq;
/*
* Mid-layer error recovery entry point semaphore.
*/
struct semaphore eh_sem;
struct semaphore wait_sem;
asd_platform_flags flags;
};
/*
* Internal data structures.
*/
typedef struct asd_init_status {
uint8_t asd_notifier_enabled;
uint8_t asd_pci_registered;
uint8_t asd_irq_registered;
uint8_t asd_ioctl_registered;
uint8_t asd_init_state;
} asd_init_status_t;
/* SMP Locking mechanism routines */
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) || defined(SCSI_HAS_HOST_LOCK))
#define SCSI_ML_HAS_HOST_LOCK 1
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
#define asd_assign_host_lock(asd) \
scsi_assign_lock((asd)->platform_data->scsi_host, \
&(asd)->platform_data->spinlock)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,21) \
&& defined(ASD_RED_HAT_LINUX_KERNEL)
#define asd_assign_host_lock(asd) \
do { \
(asd)->platform_data->scsi_host->host_lock = \
&(asd)->platform_data->spinlock; \
} while (0)
#else
#define asd_assign_host_lock(asd) \
do { \
(asd)->platform_data->scsi_host->lock = \
&(asd)->platform_data->spinlock; \
} while (0)
#endif
#else /* !SCSI_ML_HAS_HOST_LOCK */
#define SCSI_ML_HAS_HOST_LOCK 0
#define asd_assign_host_lock(asd)
#endif /* !SCSI_ML_HAS_HOST_LOCK */
/* OS utility wrappers */
#define asd_alloc_mem(size, flags) kmalloc(size, flags)
#define asd_free_mem(ptr) kfree(ptr)
/* Debug Logging macro */
#define ASD_DBG_INIT 0x01
#define ASD_DBG_INFO 0x02
#define ASD_DBG_RUNTIME_B 0x04
#define ASD_DBG_RUNTIME 0x10
#define ASD_DBG_ISR 0x20
#define ASD_DBG_ERROR 0x40
/* Debug mask to control the Debug Level printout. */
extern u_int debug_mask;
#ifdef ASD_DEBUG
#define asd_dprint(fmt, ...) printk(KERN_NOTICE fmt, ## __VA_ARGS__)
#define asd_log(debug_level, fmt, args...) \
do { \
if ((debug_level & debug_mask) != 0) { \
printk("%s(%d) : ", __FUNCTION__, __LINE__); \
printk(fmt, ##args); \
} \
} while (0)
/* For initial debugging purpose only. */
#define IN 0
#define OUT 1
#define LINE 2
#define ASD_DBG_FUNC(x) \
do { \
if (x == IN) { \
printk("+++ Entering Function: %s:%d.\n", __FUNCTION__, \
__LINE__); \
} else if (x == OUT) { \
printk("--- Exiting Function: %s:%d.\n", __FUNCTION__, \
__LINE__); \
} else { \
printk("*** %s (%d).\n", __FUNCTION__, __LINE__); \
} \
} while (0)
#if KDB_ENABLE
#define ASSERT(expression) \
if (!(expression)) { \
printk("assertion failed: %s, file: %s, line: %d\n", \
#expression, __FILE__, __LINE__); \
KDB_ENTER(); \
}
#else /* KDB_ENABLE */
#define ASSERT(expression) \
if (!(expression)) { \
panic("assertion failed: %s, file: %s, line: %d\n", \
#expression, __FILE__, __LINE__); \
}
#endif /* KDB_ENABLE */
#else /* ASD_DEBUG */
#define asd_dprint(fmt, ...)
#define asd_log(debug_level, fmt, args...) /**/
#define ASD_DBG_FUNC(x) /**/
#define ASSERT(expression)
#endif /* ASD_DEBUG */
#define asd_print(fmt, args...) printk(fmt, ##args)
#define ASD_DUMP_REG(reg) /**/
#ifndef IRQ_RETVAL
typedef void irqreturn_t;
#define IRQ_RETVAL(x) /**/
#endif
/*
* SCSI Status Byte
*/
#define SCSI_STATUS_OK 0x00
#define SCSI_STATUS_CHECK_COND 0x02
#define SCSI_STATUS_COND_MET 0x04
#define SCSI_STATUS_BUSY 0x08
#define SCSI_STATUS_INTERMED 0x10
#define SCSI_STATUS_INTERMED_COND_MET 0x14
#define SCSI_STATUS_RESERV_CONFLICT 0x18
#define SCSI_STATUS_CMD_TERMINATED 0x22 /* Obsolete in SAM-2 */
#define SCSI_STATUS_QUEUE_FULL 0x28
#define SCSI_STATUS_ACA_ACTIVE 0x30
#define SCSI_STATUS_TASK_ABORTED 0x40
struct scsi_sense_data
{
uint8_t error_code;
#define SSD_ERRCODE 0x7F
#define SSD_CURRENT_ERROR 0x70
#define SSD_DEFERRED_ERROR 0x71
#define SSD_ERRCODE_VALID 0x80
uint8_t segment;
uint8_t flags;
#define SSD_KEY 0x0F
#define SSD_KEY_NO_SENSE 0x00
#define SSD_KEY_RECOVERED_ERROR 0x01
#define SSD_KEY_NOT_READY 0x02
#define SSD_KEY_MEDIUM_ERROR 0x03
#define SSD_KEY_HARDWARE_ERROR 0x04
#define SSD_KEY_ILLEGAL_REQUEST 0x05
#define SSD_KEY_UNIT_ATTENTION 0x06
#define SSD_KEY_DATA_PROTECT 0x07
#define SSD_KEY_BLANK_CHECK 0x08
#define SSD_KEY_Vendor_Specific 0x09
#define SSD_KEY_COPY_ABORTED 0x0a
#define SSD_KEY_ABORTED_COMMAND 0x0b
#define SSD_KEY_EQUAL 0x0c
#define SSD_KEY_VOLUME_OVERFLOW 0x0d
#define SSD_KEY_MISCOMPARE 0x0e
#define SSD_KEY_RESERVED 0x0f
#define SSD_ILI 0x20
#define SSD_EOM 0x40
#define SSD_FILEMARK 0x80
uint8_t info[4];
uint8_t extra_len;
uint8_t cmd_spec_info[4];
uint8_t add_sense_code;
uint8_t add_sense_code_qual;
uint8_t fru;
uint8_t sense_key_spec[3];
#define SSD_SCS_VALID 0x80
#define SSD_FIELDPTR_CMD 0x40
#define SSD_BITPTR_VALID 0x08
#define SSD_BITPTR_VALUE 0x07
#define SSD_MIN_SIZE 18
uint8_t extra_bytes[14];
#define SSD_FULL_SIZE sizeof(struct scsi_sense_data)
};
static inline void scsi_ulto2b(uint32_t val, uint8_t *bytes);
static inline void scsi_ulto3b(uint32_t val, uint8_t *bytes);
static inline void scsi_ulto4b(uint32_t val, uint8_t *bytes);
static inline uint32_t scsi_2btoul(uint8_t *bytes);
static inline uint32_t scsi_3btoul(uint8_t *bytes);
static inline int32_t scsi_3btol(uint8_t *bytes);
static inline uint32_t scsi_4btoul(uint8_t *bytes);
static inline void
scsi_ulto2b(uint32_t val, uint8_t *bytes)
{
bytes[0] = (val >> 8) & 0xff;
bytes[1] = val & 0xff;
}
static inline void
scsi_ulto3b(uint32_t val, uint8_t *bytes)
{
bytes[0] = (val >> 16) & 0xff;
bytes[1] = (val >> 8) & 0xff;
bytes[2] = val & 0xff;
}
static inline void
scsi_ulto4b(uint32_t val, uint8_t *bytes)
{
bytes[0] = (val >> 24) & 0xff;
bytes[1] = (val >> 16) & 0xff;
bytes[2] = (val >> 8) & 0xff;
bytes[3] = val & 0xff;
}
static inline uint32_t
scsi_2btoul(uint8_t *bytes)
{
uint32_t rv;
rv = (bytes[0] << 8) |
bytes[1];
return (rv);
}
static inline uint32_t
scsi_3btoul(uint8_t *bytes)
{
uint32_t rv;
rv = (bytes[0] << 16) |
(bytes[1] << 8) |
bytes[2];
return (rv);
}
static inline int32_t
scsi_3btol(uint8_t *bytes)
{
uint32_t rc = scsi_3btoul(bytes);
if (rc & 0x00800000)
rc |= 0xff000000;
return (int32_t) rc;
}
static inline uint32_t
scsi_4btoul(uint8_t *bytes)
{
uint32_t rv;
rv = (bytes[0] << 24) |
(bytes[1] << 16) |
(bytes[2] << 8) |
bytes[3];
return (rv);
}
/*********************** Transaction Access Wrappers **************************/
static inline void asd_cmd_set_host_status(Scsi_Cmnd *cmd, u_int);
static inline void asd_cmd_set_scsi_status(Scsi_Cmnd *cmd, u_int);
static inline uint32_t asd_cmd_get_host_status(Scsi_Cmnd *cmd);
static inline uint32_t asd_cmd_get_scsi_status(Scsi_Cmnd *cmd);
static inline void asd_freeze_scb(struct scb *scb);
static inline void asd_unfreeze_scb(struct scb *scb);
#define CMD_DRIVER_STATUS_MASK 0xFF000000
#define CMD_DRIVER_STATUS_SHIFT 24
#define CMD_HOST_STATUS_MASK 0x00FF0000
#define CMD_HOST_STATUS_SHIFT 16
#define CMD_MSG_STATUS_MASK 0x0000FF00
#define CMD_MSG_STATUS_SHIFT 8
#define CMD_SCSI_STATUS_MASK 0x000000FF
#define CMD_SCSI_STATUS_SHIFT 0
#define CMD_REQ_INPROG 0xFF
static inline
void asd_cmd_set_driver_status(Scsi_Cmnd *cmd, u_int status)
{
cmd->result &= ~CMD_DRIVER_STATUS_MASK;
cmd->result |= status << CMD_DRIVER_STATUS_SHIFT;
}
static inline
void asd_cmd_set_host_status(Scsi_Cmnd *cmd, u_int status)
{
cmd->result &= ~CMD_HOST_STATUS_MASK;
cmd->result |= status << CMD_HOST_STATUS_SHIFT;
}
static inline
void asd_cmd_set_scsi_status(Scsi_Cmnd *cmd, u_int status)
{
cmd->result &= ~CMD_SCSI_STATUS_MASK;
cmd->result |= status;
}
static inline
uint32_t asd_cmd_get_host_status(Scsi_Cmnd *cmd)
{
return ((cmd->result & CMD_HOST_STATUS_MASK) >> CMD_HOST_STATUS_SHIFT);
}
static inline
uint32_t asd_cmd_get_scsi_status(Scsi_Cmnd *cmd)
{
return ((cmd->result & CMD_SCSI_STATUS_MASK) >> CMD_SCSI_STATUS_SHIFT);
}
static inline void
asd_freeze_scb(struct scb *scb)
{
if ((scb->flags & SCB_DEV_QFRZN) == 0) {
scb->flags |= SCB_DEV_QFRZN;
scb->platform_data->dev->qfrozen++;
}
}
static inline void
asd_unfreeze_scb(struct scb *scb)
{
if ((scb->flags & SCB_DEV_QFRZN) != 0) {
scb->flags &= ~SCB_DEV_QFRZN;
scb->platform_data->dev->qfrozen--;
}
}
// TODO - where is right spot for these???
typedef enum {
ASD_COMMAND_BUILD_OK,
ASD_COMMAND_BUILD_FAILED,
ASD_COMMAND_BUILD_FINISHED
} ASD_COMMAND_BUILD_STATUS;
ASD_COMMAND_BUILD_STATUS
asd_setup_data(struct asd_softc *asd, struct scb *scb, Scsi_Cmnd *cmd);
DISCOVER_RESULTS
asd_do_discovery(struct asd_softc *asd, struct asd_port *port);
DISCOVER_RESULTS
asd_run_state_machine(struct state_machine_context *sm_contextp);
int asd_platform_alloc(struct asd_softc *asd);
void asd_platform_free(struct asd_softc *asd);
struct asd_scb_platform_data *
asd_alloc_scb_platform_data(struct asd_softc *asd);
void asd_free_scb_platform_data(struct asd_softc *asd,
struct asd_scb_platform_data *pdata);
void asd_unmap_scb(struct asd_softc *asd, struct scb *scb);
void asd_recover_cmds(struct asd_softc *asd);
void asd_hwi_release_sata_spinup_hold(struct asd_softc *asd,
struct asd_phy *phy);
struct asd_target *
asd_alloc_target(struct asd_softc *asd, struct asd_port *src_port);
void asd_free_target(struct asd_softc *asd, struct asd_target *targ);
int asd_map_target(struct asd_softc *asd, struct asd_target *targ);
struct asd_device *
asd_alloc_device(struct asd_softc *asd, struct asd_target *targ,
u_int ch, u_int id, u_int lun);
void asd_free_device(struct asd_softc *asd, struct asd_device *dev);
struct asd_device *
asd_get_device(struct asd_softc *asd, u_int ch, u_int id,
u_int lun, int alloc);
void asd_remap_device(struct asd_softc *asd, struct asd_target *target,
struct asd_target *multipath_target);
void asd_timed_run_dev_queue(u_long arg);
#if defined(__VMKLNX__)
void asd_destroy_device(struct work_struct *arg);
#else /* !defined(__VMKLNX__) */
void asd_destroy_device(void *arg);
#endif /* defined(__VMKLNX__) */
#ifndef list_for_each_entry_safe
/**
* list_for_each_entry_safe - iterate over list of given type safe against
* removal of list entry
* @pos: the type * to use as a loop counter.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
n = list_entry(pos->member.next, typeof(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeof(*n), member))
#endif
#ifndef list_for_each_entry
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop counter.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member), \
prefetch(pos->member.next); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member), \
prefetch(pos->member.next))
#endif
#define list_move_all(to_list, from_list) \
if (!list_empty(from_list)) { \
(to_list)->next = (from_list)->next; \
(to_list)->prev = (from_list)->prev; \
(from_list)->next->prev = to_list; \
(from_list)->prev->next = to_list; \
INIT_LIST_HEAD(from_list); \
} else { \
INIT_LIST_HEAD(to_list); \
}
#define list_copy(to_list, from_list) \
do { \
(to_list)->next = (from_list)->next; \
(to_list)->prev = (from_list)->prev; \
} while (0)
void asd_hwi_set_ddbsite_byte(struct asd_softc *asd,
uint16_t site_offset, uint8_t val);
void asd_hwi_set_ddbsite_word(struct asd_softc *asd,
uint16_t site_offset, uint16_t val);
void asd_hwi_set_ddbsite_dword(struct asd_softc *asd,
uint16_t site_offset, uint32_t val);
uint8_t asd_hwi_get_ddbsite_byte(struct asd_softc *asd,
uint16_t site_offset);
uint16_t asd_hwi_get_ddbsite_word(struct asd_softc *asd,
uint16_t site_offset);
uint32_t asd_hwi_get_ddbsite_dword(struct asd_softc *asd,
uint16_t site_offset);
#endif /* ADP94XX_OSM_H */
|