1/* 2 * Aic94xx SAS/SATA driver access to shared data structures and memory 3 * maps. 4 * 5 * Copyright (C) 2005 Adaptec, Inc. All rights reserved. 6 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com> 7 * 8 * This file is licensed under GPLv2. 9 * 10 * This file is part of the aic94xx driver. 11 * 12 * The aic94xx driver is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License as 14 * published by the Free Software Foundation; version 2 of the 15 * License. 16 * 17 * The aic94xx driver is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 * General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with the aic94xx driver; if not, write to the Free Software 24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 25 * 26 */ 27 28#include <linux/pci.h> 29#include <linux/delay.h> 30 31#include "aic94xx.h" 32#include "aic94xx_reg.h" 33 34/* ---------- OCM stuff ---------- */ 35 36struct asd_ocm_dir_ent { 37 u8 type; 38 u8 offs[3]; 39 u8 _r1; 40 u8 size[3]; 41} __attribute__ ((packed)); 42 43struct asd_ocm_dir { 44 char sig[2]; 45 u8 _r1[2]; 46 u8 major; /* 0 */ 47 u8 minor; /* 0 */ 48 u8 _r2; 49 u8 num_de; 50 struct asd_ocm_dir_ent entry[15]; 51} __attribute__ ((packed)); 52 53#define OCM_DE_OCM_DIR 0x00 54#define OCM_DE_WIN_DRVR 0x01 55#define OCM_DE_BIOS_CHIM 0x02 56#define OCM_DE_RAID_ENGN 0x03 57#define OCM_DE_BIOS_INTL 0x04 58#define OCM_DE_BIOS_CHIM_OSM 0x05 59#define OCM_DE_BIOS_CHIM_DYNAMIC 0x06 60#define OCM_DE_ADDC2C_RES0 0x07 61#define OCM_DE_ADDC2C_RES1 0x08 62#define OCM_DE_ADDC2C_RES2 0x09 63#define OCM_DE_ADDC2C_RES3 0x0A 64 65#define OCM_INIT_DIR_ENTRIES 5 66/*************************************************************************** 67* OCM directory default 68***************************************************************************/ 69static struct asd_ocm_dir OCMDirInit = 70{ 71 .sig = {0x4D, 0x4F}, /* signature */ 72 .num_de = OCM_INIT_DIR_ENTRIES, /* no. of directory entries */ 73}; 74 75/*************************************************************************** 76* OCM directory Entries default 77***************************************************************************/ 78static struct asd_ocm_dir_ent OCMDirEntriesInit[OCM_INIT_DIR_ENTRIES] = 79{ 80 { 81 .type = (OCM_DE_ADDC2C_RES0), /* Entry type */ 82 .offs = {128}, /* Offset */ 83 .size = {0, 4}, /* size */ 84 }, 85 { 86 .type = (OCM_DE_ADDC2C_RES1), /* Entry type */ 87 .offs = {128, 4}, /* Offset */ 88 .size = {0, 4}, /* size */ 89 }, 90 { 91 .type = (OCM_DE_ADDC2C_RES2), /* Entry type */ 92 .offs = {128, 8}, /* Offset */ 93 .size = {0, 4}, /* size */ 94 }, 95 { 96 .type = (OCM_DE_ADDC2C_RES3), /* Entry type */ 97 .offs = {128, 12}, /* Offset */ 98 .size = {0, 4}, /* size */ 99 }, 100 { 101 .type = (OCM_DE_WIN_DRVR), /* Entry type */ 102 .offs = {128, 16}, /* Offset */ 103 .size = {128, 235, 1}, /* size */ 104 }, 105}; 106 107struct asd_bios_chim_struct { 108 char sig[4]; 109 u8 major; /* 1 */ 110 u8 minor; /* 0 */ 111 u8 bios_major; 112 u8 bios_minor; 113 __le32 bios_build; 114 u8 flags; 115 u8 pci_slot; 116 __le16 ue_num; 117 __le16 ue_size; 118 u8 _r[14]; 119 /* The unit element array is right here. 120 */ 121} __attribute__ ((packed)); 122 123/** 124 * asd_read_ocm_seg - read an on chip memory (OCM) segment 125 * @asd_ha: pointer to the host adapter structure 126 * @buffer: where to write the read data 127 * @offs: offset into OCM where to read from 128 * @size: how many bytes to read 129 * 130 * Return the number of bytes not read. Return 0 on success. 131 */ 132static int asd_read_ocm_seg(struct asd_ha_struct *asd_ha, void *buffer, 133 u32 offs, int size) 134{ 135 u8 *p = buffer; 136 if (unlikely(asd_ha->iospace)) 137 asd_read_reg_string(asd_ha, buffer, offs+OCM_BASE_ADDR, size); 138 else { 139 for ( ; size > 0; size--, offs++, p++) 140 *p = asd_read_ocm_byte(asd_ha, offs); 141 } 142 return size; 143} 144 145static int asd_read_ocm_dir(struct asd_ha_struct *asd_ha, 146 struct asd_ocm_dir *dir, u32 offs) 147{ 148 int err = asd_read_ocm_seg(asd_ha, dir, offs, sizeof(*dir)); 149 if (err) { 150 ASD_DPRINTK("couldn't read ocm segment\n"); 151 return err; 152 } 153 154 if (dir->sig[0] != 'M' || dir->sig[1] != 'O') { 155 ASD_DPRINTK("no valid dir signature(%c%c) at start of OCM\n", 156 dir->sig[0], dir->sig[1]); 157 return -ENOENT; 158 } 159 if (dir->major != 0) { 160 asd_printk("unsupported major version of ocm dir:0x%x\n", 161 dir->major); 162 return -ENOENT; 163 } 164 dir->num_de &= 0xf; 165 return 0; 166} 167 168/** 169 * asd_write_ocm_seg - write an on chip memory (OCM) segment 170 * @asd_ha: pointer to the host adapter structure 171 * @buffer: where to read the write data 172 * @offs: offset into OCM to write to 173 * @size: how many bytes to write 174 * 175 * Return the number of bytes not written. Return 0 on success. 176 */ 177static void asd_write_ocm_seg(struct asd_ha_struct *asd_ha, void *buffer, 178 u32 offs, int size) 179{ 180 u8 *p = buffer; 181 if (unlikely(asd_ha->iospace)) 182 asd_write_reg_string(asd_ha, buffer, offs+OCM_BASE_ADDR, size); 183 else { 184 for ( ; size > 0; size--, offs++, p++) 185 asd_write_ocm_byte(asd_ha, offs, *p); 186 } 187 return; 188} 189 190#define THREE_TO_NUM(X) ((X)[0] | ((X)[1] << 8) | ((X)[2] << 16)) 191 192static int asd_find_dir_entry(struct asd_ocm_dir *dir, u8 type, 193 u32 *offs, u32 *size) 194{ 195 int i; 196 struct asd_ocm_dir_ent *ent; 197 198 for (i = 0; i < dir->num_de; i++) { 199 if (dir->entry[i].type == type) 200 break; 201 } 202 if (i >= dir->num_de) 203 return -ENOENT; 204 ent = &dir->entry[i]; 205 *offs = (u32) THREE_TO_NUM(ent->offs); 206 *size = (u32) THREE_TO_NUM(ent->size); 207 return 0; 208} 209 210#define OCM_BIOS_CHIM_DE 2 211#define BC_BIOS_PRESENT 1 212 213static int asd_get_bios_chim(struct asd_ha_struct *asd_ha, 214 struct asd_ocm_dir *dir) 215{ 216 int err; 217 struct asd_bios_chim_struct *bc_struct; 218 u32 offs, size; 219 220 err = asd_find_dir_entry(dir, OCM_BIOS_CHIM_DE, &offs, &size); 221 if (err) { 222 ASD_DPRINTK("couldn't find BIOS_CHIM dir ent\n"); 223 goto out; 224 } 225 err = -ENOMEM; 226 bc_struct = kmalloc(sizeof(*bc_struct), GFP_KERNEL); 227 if (!bc_struct) { 228 asd_printk("no memory for bios_chim struct\n"); 229 goto out; 230 } 231 err = asd_read_ocm_seg(asd_ha, (void *)bc_struct, offs, 232 sizeof(*bc_struct)); 233 if (err) { 234 ASD_DPRINTK("couldn't read ocm segment\n"); 235 goto out2; 236 } 237 if (strncmp(bc_struct->sig, "SOIB", 4) 238 && strncmp(bc_struct->sig, "IPSA", 4)) { 239 ASD_DPRINTK("BIOS_CHIM entry has no valid sig(%c%c%c%c)\n", 240 bc_struct->sig[0], bc_struct->sig[1], 241 bc_struct->sig[2], bc_struct->sig[3]); 242 err = -ENOENT; 243 goto out2; 244 } 245 if (bc_struct->major != 1) { 246 asd_printk("BIOS_CHIM unsupported major version:0x%x\n", 247 bc_struct->major); 248 err = -ENOENT; 249 goto out2; 250 } 251 if (bc_struct->flags & BC_BIOS_PRESENT) { 252 asd_ha->hw_prof.bios.present = 1; 253 asd_ha->hw_prof.bios.maj = bc_struct->bios_major; 254 asd_ha->hw_prof.bios.min = bc_struct->bios_minor; 255 asd_ha->hw_prof.bios.bld = le32_to_cpu(bc_struct->bios_build); 256 ASD_DPRINTK("BIOS present (%d,%d), %d\n", 257 asd_ha->hw_prof.bios.maj, 258 asd_ha->hw_prof.bios.min, 259 asd_ha->hw_prof.bios.bld); 260 } 261 asd_ha->hw_prof.ue.num = le16_to_cpu(bc_struct->ue_num); 262 asd_ha->hw_prof.ue.size= le16_to_cpu(bc_struct->ue_size); 263 ASD_DPRINTK("ue num:%d, ue size:%d\n", asd_ha->hw_prof.ue.num, 264 asd_ha->hw_prof.ue.size); 265 size = asd_ha->hw_prof.ue.num * asd_ha->hw_prof.ue.size; 266 if (size > 0) { 267 err = -ENOMEM; 268 asd_ha->hw_prof.ue.area = kmalloc(size, GFP_KERNEL); 269 if (!asd_ha->hw_prof.ue.area) 270 goto out2; 271 err = asd_read_ocm_seg(asd_ha, (void *)asd_ha->hw_prof.ue.area, 272 offs + sizeof(*bc_struct), size); 273 if (err) { 274 kfree(asd_ha->hw_prof.ue.area); 275 asd_ha->hw_prof.ue.area = NULL; 276 asd_ha->hw_prof.ue.num = 0; 277 asd_ha->hw_prof.ue.size = 0; 278 ASD_DPRINTK("couldn't read ue entries(%d)\n", err); 279 } 280 } 281out2: 282 kfree(bc_struct); 283out: 284 return err; 285} 286 287static void 288asd_hwi_initialize_ocm_dir (struct asd_ha_struct *asd_ha) 289{ 290 int i; 291 292 /* Zero OCM */ 293 for (i = 0; i < OCM_MAX_SIZE; i += 4) 294 asd_write_ocm_dword(asd_ha, i, 0); 295 296 /* Write Dir */ 297 asd_write_ocm_seg(asd_ha, &OCMDirInit, 0, 298 sizeof(struct asd_ocm_dir)); 299 300 /* Write Dir Entries */ 301 for (i = 0; i < OCM_INIT_DIR_ENTRIES; i++) 302 asd_write_ocm_seg(asd_ha, &OCMDirEntriesInit[i], 303 sizeof(struct asd_ocm_dir) + 304 (i * sizeof(struct asd_ocm_dir_ent)) 305 , sizeof(struct asd_ocm_dir_ent)); 306 307} 308 309static int 310asd_hwi_check_ocm_access (struct asd_ha_struct *asd_ha) 311{ 312 struct pci_dev *pcidev = asd_ha->pcidev; 313 u32 reg; 314 int err = 0; 315 u32 v; 316 317 /* check if OCM has been initialized by BIOS */ 318 reg = asd_read_reg_dword(asd_ha, EXSICNFGR); 319 320 if (!(reg & OCMINITIALIZED)) { 321 err = pci_read_config_dword(pcidev, PCIC_INTRPT_STAT, &v); 322 if (err) { 323 asd_printk("couldn't access PCIC_INTRPT_STAT of %s\n", 324 pci_name(pcidev)); 325 goto out; 326 } 327 328 printk(KERN_INFO "OCM is not initialized by BIOS," 329 "reinitialize it and ignore it, current IntrptStatus" 330 "is 0x%x\n", v); 331 332 if (v) 333 err = pci_write_config_dword(pcidev, 334 PCIC_INTRPT_STAT, v); 335 if (err) { 336 asd_printk("couldn't write PCIC_INTRPT_STAT of %s\n", 337 pci_name(pcidev)); 338 goto out; 339 } 340 341 asd_hwi_initialize_ocm_dir(asd_ha); 342 343 } 344out: 345 return err; 346} 347 348/** 349 * asd_read_ocm - read on chip memory (OCM) 350 * @asd_ha: pointer to the host adapter structure 351 */ 352int asd_read_ocm(struct asd_ha_struct *asd_ha) 353{ 354 int err; 355 struct asd_ocm_dir *dir; 356 357 if (asd_hwi_check_ocm_access(asd_ha)) 358 return -1; 359 360 dir = kmalloc(sizeof(*dir), GFP_KERNEL); 361 if (!dir) { 362 asd_printk("no memory for ocm dir\n"); 363 return -ENOMEM; 364 } 365 366 err = asd_read_ocm_dir(asd_ha, dir, 0); 367 if (err) 368 goto out; 369 370 err = asd_get_bios_chim(asd_ha, dir); 371out: 372 kfree(dir); 373 return err; 374} 375 376/* ---------- FLASH stuff ---------- */ 377 378#define FLASH_RESET 0xF0 379 380#define FLASH_SIZE 0x200000 381#define FLASH_DIR_COOKIE "*** ADAPTEC FLASH DIRECTORY *** " 382#define FLASH_NEXT_ENTRY_OFFS 0x2000 383#define FLASH_MAX_DIR_ENTRIES 32 384 385#define FLASH_DE_TYPE_MASK 0x3FFFFFFF 386#define FLASH_DE_MS 0x120 387#define FLASH_DE_CTRL_A_USER 0xE0 388 389struct asd_flash_de { 390 __le32 type; 391 __le32 offs; 392 __le32 pad_size; 393 __le32 image_size; 394 __le32 chksum; 395 u8 _r[12]; 396 u8 version[32]; 397} __attribute__ ((packed)); 398 399struct asd_flash_dir { 400 u8 cookie[32]; 401 __le32 rev; /* 2 */ 402 __le32 chksum; 403 __le32 chksum_antidote; 404 __le32 bld; 405 u8 bld_id[32]; /* build id data */ 406 u8 ver_data[32]; /* date and time of build */ 407 __le32 ae_mask; 408 __le32 v_mask; 409 __le32 oc_mask; 410 u8 _r[20]; 411 struct asd_flash_de dir_entry[FLASH_MAX_DIR_ENTRIES]; 412} __attribute__ ((packed)); 413 414struct asd_manuf_sec { 415 char sig[2]; /* 'S', 'M' */ 416 u16 offs_next; 417 u8 maj; /* 0 */ 418 u8 min; /* 0 */ 419 u16 chksum; 420 u16 size; 421 u8 _r[6]; 422 u8 sas_addr[SAS_ADDR_SIZE]; 423 u8 pcba_sn[ASD_PCBA_SN_SIZE]; 424 /* Here start the other segments */ 425 u8 linked_list[0]; 426} __attribute__ ((packed)); 427 428struct asd_manuf_phy_desc { 429 u8 state; /* low 4 bits */ 430#define MS_PHY_STATE_ENABLED 0 431#define MS_PHY_STATE_REPORTED 1 432#define MS_PHY_STATE_HIDDEN 2 433 u8 phy_id; 434 u16 _r; 435 u8 phy_control_0; /* mode 5 reg 0x160 */ 436 u8 phy_control_1; /* mode 5 reg 0x161 */ 437 u8 phy_control_2; /* mode 5 reg 0x162 */ 438 u8 phy_control_3; /* mode 5 reg 0x163 */ 439} __attribute__ ((packed)); 440 441struct asd_manuf_phy_param { 442 char sig[2]; /* 'P', 'M' */ 443 u16 next; 444 u8 maj; /* 0 */ 445 u8 min; /* 2 */ 446 u8 num_phy_desc; /* 8 */ 447 u8 phy_desc_size; /* 8 */ 448 u8 _r[3]; 449 u8 usage_model_id; 450 u32 _r2; 451 struct asd_manuf_phy_desc phy_desc[ASD_MAX_PHYS]; 452} __attribute__ ((packed)); 453 454 455struct asd_ms_sb_desc { 456 u8 type; 457 u8 node_desc_index; 458 u8 conn_desc_index; 459 u8 _recvd[0]; 460} __attribute__ ((packed)); 461 462 463struct asd_ms_conn_desc { 464 u8 type; 465 u8 location; 466 u8 num_sideband_desc; 467 u8 size_sideband_desc; 468 u32 _resvd; 469 u8 name[16]; 470 struct asd_ms_sb_desc sb_desc[0]; 471} __attribute__ ((packed)); 472 473struct asd_nd_phy_desc { 474 u8 vp_attch_type; 475 u8 attch_specific[0]; 476} __attribute__ ((packed)); 477 478 479struct asd_ms_node_desc { 480 u8 type; 481 u8 num_phy_desc; 482 u8 size_phy_desc; 483 u8 _resvd; 484 u8 name[16]; 485 struct asd_nd_phy_desc phy_desc[0]; 486} __attribute__ ((packed)); 487 488struct asd_ms_conn_map { 489 char sig[2]; /* 'M', 'C' */ 490 __le16 next; 491 u8 maj; /* 0 */ 492 u8 min; /* 0 */ 493 __le16 cm_size; /* size of this struct */ 494 u8 num_conn; 495 u8 conn_size; 496 u8 num_nodes; 497 u8 usage_model_id; 498 u32 _resvd; 499 struct asd_ms_conn_desc conn_desc[0]; 500 struct asd_ms_node_desc node_desc[0]; 501} __attribute__ ((packed)); 502 503struct asd_ctrla_phy_entry { 504 u8 sas_addr[SAS_ADDR_SIZE]; 505 u8 sas_link_rates; /* max in hi bits, min in low bits */ 506 u8 flags; 507 u8 sata_link_rates; 508 u8 _r[5]; 509} __attribute__ ((packed)); 510 511struct asd_ctrla_phy_settings { 512 u8 id0; /* P'h'y */ 513 u8 _r; 514 u16 next; 515 u8 num_phys; /* number of PHYs in the PCI function */ 516 u8 _r2[3]; 517 struct asd_ctrla_phy_entry phy_ent[ASD_MAX_PHYS]; 518} __attribute__ ((packed)); 519 520struct asd_ll_el { 521 u8 id0; 522 u8 id1; 523 __le16 next; 524 u8 something_here[0]; 525} __attribute__ ((packed)); 526 527static int asd_poll_flash(struct asd_ha_struct *asd_ha) 528{ 529 int c; 530 u8 d; 531 532 for (c = 5000; c > 0; c--) { 533 d = asd_read_reg_byte(asd_ha, asd_ha->hw_prof.flash.bar); 534 d ^= asd_read_reg_byte(asd_ha, asd_ha->hw_prof.flash.bar); 535 if (!d) 536 return 0; 537 udelay(5); 538 } 539 return -ENOENT; 540} 541 542static int asd_reset_flash(struct asd_ha_struct *asd_ha) 543{ 544 int err; 545 546 err = asd_poll_flash(asd_ha); 547 if (err) 548 return err; 549 asd_write_reg_byte(asd_ha, asd_ha->hw_prof.flash.bar, FLASH_RESET); 550 err = asd_poll_flash(asd_ha); 551 552 return err; 553} 554 555static inline int asd_read_flash_seg(struct asd_ha_struct *asd_ha, 556 void *buffer, u32 offs, int size) 557{ 558 asd_read_reg_string(asd_ha, buffer, asd_ha->hw_prof.flash.bar+offs, 559 size); 560 return 0; 561} 562 563/** 564 * asd_find_flash_dir - finds and reads the flash directory 565 * @asd_ha: pointer to the host adapter structure 566 * @flash_dir: pointer to flash directory structure 567 * 568 * If found, the flash directory segment will be copied to 569 * @flash_dir. Return 1 if found, 0 if not. 570 */ 571static int asd_find_flash_dir(struct asd_ha_struct *asd_ha, 572 struct asd_flash_dir *flash_dir) 573{ 574 u32 v; 575 for (v = 0; v < FLASH_SIZE; v += FLASH_NEXT_ENTRY_OFFS) { 576 asd_read_flash_seg(asd_ha, flash_dir, v, 577 sizeof(FLASH_DIR_COOKIE)-1); 578 if (memcmp(flash_dir->cookie, FLASH_DIR_COOKIE, 579 sizeof(FLASH_DIR_COOKIE)-1) == 0) { 580 asd_ha->hw_prof.flash.dir_offs = v; 581 asd_read_flash_seg(asd_ha, flash_dir, v, 582 sizeof(*flash_dir)); 583 return 1; 584 } 585 } 586 return 0; 587} 588 589static int asd_flash_getid(struct asd_ha_struct *asd_ha) 590{ 591 int err = 0; 592 u32 reg; 593 594 reg = asd_read_reg_dword(asd_ha, EXSICNFGR); 595 596 if (pci_read_config_dword(asd_ha->pcidev, PCI_CONF_FLSH_BAR, 597 &asd_ha->hw_prof.flash.bar)) { 598 asd_printk("couldn't read PCI_CONF_FLSH_BAR of %s\n", 599 pci_name(asd_ha->pcidev)); 600 return -ENOENT; 601 } 602 asd_ha->hw_prof.flash.present = 1; 603 asd_ha->hw_prof.flash.wide = reg & FLASHW ? 1 : 0; 604 err = asd_reset_flash(asd_ha); 605 if (err) { 606 ASD_DPRINTK("couldn't reset flash(%d)\n", err); 607 return err; 608 } 609 return 0; 610} 611 612static u16 asd_calc_flash_chksum(u16 *p, int size) 613{ 614 u16 chksum = 0; 615 616 while (size-- > 0) 617 chksum += *p++; 618 619 return chksum; 620} 621 622 623static int asd_find_flash_de(struct asd_flash_dir *flash_dir, u32 entry_type, 624 u32 *offs, u32 *size) 625{ 626 int i; 627 struct asd_flash_de *de; 628 629 for (i = 0; i < FLASH_MAX_DIR_ENTRIES; i++) { 630 u32 type = le32_to_cpu(flash_dir->dir_entry[i].type); 631 632 type &= FLASH_DE_TYPE_MASK; 633 if (type == entry_type) 634 break; 635 } 636 if (i >= FLASH_MAX_DIR_ENTRIES) 637 return -ENOENT; 638 de = &flash_dir->dir_entry[i]; 639 *offs = le32_to_cpu(de->offs); 640 *size = le32_to_cpu(de->pad_size); 641 return 0; 642} 643 644static int asd_validate_ms(struct asd_manuf_sec *ms) 645{ 646 if (ms->sig[0] != 'S' || ms->sig[1] != 'M') { 647 ASD_DPRINTK("manuf sec: no valid sig(%c%c)\n", 648 ms->sig[0], ms->sig[1]); 649 return -ENOENT; 650 } 651 if (ms->maj != 0) { 652 asd_printk("unsupported manuf. sector. major version:%x\n", 653 ms->maj); 654 return -ENOENT; 655 } 656 ms->offs_next = le16_to_cpu((__force __le16) ms->offs_next); 657 ms->chksum = le16_to_cpu((__force __le16) ms->chksum); 658 ms->size = le16_to_cpu((__force __le16) ms->size); 659 660 if (asd_calc_flash_chksum((u16 *)ms, ms->size/2)) { 661 asd_printk("failed manuf sector checksum\n"); 662 } 663 664 return 0; 665} 666 667static int asd_ms_get_sas_addr(struct asd_ha_struct *asd_ha, 668 struct asd_manuf_sec *ms) 669{ 670 memcpy(asd_ha->hw_prof.sas_addr, ms->sas_addr, SAS_ADDR_SIZE); 671 return 0; 672} 673 674static int asd_ms_get_pcba_sn(struct asd_ha_struct *asd_ha, 675 struct asd_manuf_sec *ms) 676{ 677 memcpy(asd_ha->hw_prof.pcba_sn, ms->pcba_sn, ASD_PCBA_SN_SIZE); 678 asd_ha->hw_prof.pcba_sn[ASD_PCBA_SN_SIZE] = '\0'; 679 return 0; 680} 681 682/** 683 * asd_find_ll_by_id - find a linked list entry by its id 684 * @start: void pointer to the first element in the linked list 685 * @id0: the first byte of the id (offs 0) 686 * @id1: the second byte of the id (offs 1) 687 * 688 * @start has to be the _base_ element start, since the 689 * linked list entries's offset is from this pointer. 690 * Some linked list entries use only the first id, in which case 691 * you can pass 0xFF for the second. 692 */ 693static void *asd_find_ll_by_id(void * const start, const u8 id0, const u8 id1) 694{ 695 struct asd_ll_el *el = start; 696 697 do { 698 switch (id1) { 699 default: 700 if (el->id1 == id1) 701 case 0xFF: 702 if (el->id0 == id0) 703 return el; 704 } 705 el = start + le16_to_cpu(el->next); 706 } while (el != start); 707 708 return NULL; 709} 710 711/** 712 * asd_ms_get_phy_params - get phy parameters from the manufacturing sector 713 * @asd_ha: pointer to the host adapter structure 714 * @manuf_sec: pointer to the manufacturing sector 715 * 716 * The manufacturing sector contans also the linked list of sub-segments, 717 * since when it was read, its size was taken from the flash directory, 718 * not from the structure size. 719 * 720 * HIDDEN phys do not count in the total count. REPORTED phys cannot 721 * be enabled but are reported and counted towards the total. 722 * ENABLED phys are enabled by default and count towards the total. 723 * The absolute total phy number is ASD_MAX_PHYS. hw_prof->num_phys 724 * merely specifies the number of phys the host adapter decided to 725 * report. E.g., it is possible for phys 0, 1 and 2 to be HIDDEN, 726 * phys 3, 4 and 5 to be REPORTED and phys 6 and 7 to be ENABLED. 727 * In this case ASD_MAX_PHYS is 8, hw_prof->num_phys is 5, and only 2 728 * are actually enabled (enabled by default, max number of phys 729 * enableable in this case). 730 */ 731static int asd_ms_get_phy_params(struct asd_ha_struct *asd_ha, 732 struct asd_manuf_sec *manuf_sec) 733{ 734 int i; 735 int en_phys = 0; 736 int rep_phys = 0; 737 struct asd_manuf_phy_param *phy_param; 738 struct asd_manuf_phy_param dflt_phy_param; 739 740 phy_param = asd_find_ll_by_id(manuf_sec, 'P', 'M'); 741 if (!phy_param) { 742 ASD_DPRINTK("ms: no phy parameters found\n"); 743 ASD_DPRINTK("ms: Creating default phy parameters\n"); 744 dflt_phy_param.sig[0] = 'P'; 745 dflt_phy_param.sig[1] = 'M'; 746 dflt_phy_param.maj = 0; 747 dflt_phy_param.min = 2; 748 dflt_phy_param.num_phy_desc = 8; 749 dflt_phy_param.phy_desc_size = sizeof(struct asd_manuf_phy_desc); 750 for (i =0; i < ASD_MAX_PHYS; i++) { 751 dflt_phy_param.phy_desc[i].state = 0; 752 dflt_phy_param.phy_desc[i].phy_id = i; 753 dflt_phy_param.phy_desc[i].phy_control_0 = 0xf6; 754 dflt_phy_param.phy_desc[i].phy_control_1 = 0x10; 755 dflt_phy_param.phy_desc[i].phy_control_2 = 0x43; 756 dflt_phy_param.phy_desc[i].phy_control_3 = 0xeb; 757 } 758 759 phy_param = &dflt_phy_param; 760 761 } 762 763 if (phy_param->maj != 0) { 764 asd_printk("unsupported manuf. phy param major version:0x%x\n", 765 phy_param->maj); 766 return -ENOENT; 767 } 768 769 ASD_DPRINTK("ms: num_phy_desc: %d\n", phy_param->num_phy_desc); 770 asd_ha->hw_prof.enabled_phys = 0; 771 for (i = 0; i < phy_param->num_phy_desc; i++) { 772 struct asd_manuf_phy_desc *pd = &phy_param->phy_desc[i]; 773 switch (pd->state & 0xF) { 774 case MS_PHY_STATE_HIDDEN: 775 ASD_DPRINTK("ms: phy%d: HIDDEN\n", i); 776 continue; 777 case MS_PHY_STATE_REPORTED: 778 ASD_DPRINTK("ms: phy%d: REPORTED\n", i); 779 asd_ha->hw_prof.enabled_phys &= ~(1 << i); 780 rep_phys++; 781 continue; 782 case MS_PHY_STATE_ENABLED: 783 ASD_DPRINTK("ms: phy%d: ENABLED\n", i); 784 asd_ha->hw_prof.enabled_phys |= (1 << i); 785 en_phys++; 786 break; 787 } 788 asd_ha->hw_prof.phy_desc[i].phy_control_0 = pd->phy_control_0; 789 asd_ha->hw_prof.phy_desc[i].phy_control_1 = pd->phy_control_1; 790 asd_ha->hw_prof.phy_desc[i].phy_control_2 = pd->phy_control_2; 791 asd_ha->hw_prof.phy_desc[i].phy_control_3 = pd->phy_control_3; 792 } 793 asd_ha->hw_prof.max_phys = rep_phys + en_phys; 794 asd_ha->hw_prof.num_phys = en_phys; 795 ASD_DPRINTK("ms: max_phys:0x%x, num_phys:0x%x\n", 796 asd_ha->hw_prof.max_phys, asd_ha->hw_prof.num_phys); 797 ASD_DPRINTK("ms: enabled_phys:0x%x\n", asd_ha->hw_prof.enabled_phys); 798 return 0; 799} 800 801static int asd_ms_get_connector_map(struct asd_ha_struct *asd_ha, 802 struct asd_manuf_sec *manuf_sec) 803{ 804 struct asd_ms_conn_map *cm; 805 806 cm = asd_find_ll_by_id(manuf_sec, 'M', 'C'); 807 if (!cm) { 808 ASD_DPRINTK("ms: no connector map found\n"); 809 return 0; 810 } 811 812 if (cm->maj != 0) { 813 ASD_DPRINTK("ms: unsupported: connector map major version 0x%x" 814 "\n", cm->maj); 815 return -ENOENT; 816 } 817 818 819 return 0; 820} 821 822 823/** 824 * asd_process_ms - find and extract information from the manufacturing sector 825 * @asd_ha: pointer to the host adapter structure 826 * @flash_dir: pointer to the flash directory 827 */ 828static int asd_process_ms(struct asd_ha_struct *asd_ha, 829 struct asd_flash_dir *flash_dir) 830{ 831 int err; 832 struct asd_manuf_sec *manuf_sec; 833 u32 offs, size; 834 835 err = asd_find_flash_de(flash_dir, FLASH_DE_MS, &offs, &size); 836 if (err) { 837 ASD_DPRINTK("Couldn't find the manuf. sector\n"); 838 goto out; 839 } 840 841 if (size == 0) 842 goto out; 843 844 err = -ENOMEM; 845 manuf_sec = kmalloc(size, GFP_KERNEL); 846 if (!manuf_sec) { 847 ASD_DPRINTK("no mem for manuf sector\n"); 848 goto out; 849 } 850 851 err = asd_read_flash_seg(asd_ha, (void *)manuf_sec, offs, size); 852 if (err) { 853 ASD_DPRINTK("couldn't read manuf sector at 0x%x, size 0x%x\n", 854 offs, size); 855 goto out2; 856 } 857 858 err = asd_validate_ms(manuf_sec); 859 if (err) { 860 ASD_DPRINTK("couldn't validate manuf sector\n"); 861 goto out2; 862 } 863 864 err = asd_ms_get_sas_addr(asd_ha, manuf_sec); 865 if (err) { 866 ASD_DPRINTK("couldn't read the SAS_ADDR\n"); 867 goto out2; 868 } 869 ASD_DPRINTK("manuf sect SAS_ADDR %llx\n", 870 SAS_ADDR(asd_ha->hw_prof.sas_addr)); 871 872 err = asd_ms_get_pcba_sn(asd_ha, manuf_sec); 873 if (err) { 874 ASD_DPRINTK("couldn't read the PCBA SN\n"); 875 goto out2; 876 } 877 ASD_DPRINTK("manuf sect PCBA SN %s\n", asd_ha->hw_prof.pcba_sn); 878 879 err = asd_ms_get_phy_params(asd_ha, manuf_sec); 880 if (err) { 881 ASD_DPRINTK("ms: couldn't get phy parameters\n"); 882 goto out2; 883 } 884 885 err = asd_ms_get_connector_map(asd_ha, manuf_sec); 886 if (err) { 887 ASD_DPRINTK("ms: couldn't get connector map\n"); 888 goto out2; 889 } 890 891out2: 892 kfree(manuf_sec); 893out: 894 return err; 895} 896 897static int asd_process_ctrla_phy_settings(struct asd_ha_struct *asd_ha, 898 struct asd_ctrla_phy_settings *ps) 899{ 900 int i; 901 for (i = 0; i < ps->num_phys; i++) { 902 struct asd_ctrla_phy_entry *pe = &ps->phy_ent[i]; 903 904 if (!PHY_ENABLED(asd_ha, i)) 905 continue; 906 if (*(u64 *)pe->sas_addr == 0) { 907 asd_ha->hw_prof.enabled_phys &= ~(1 << i); 908 continue; 909 } 910 /* This is the SAS address which should be sent in IDENTIFY. */ 911 memcpy(asd_ha->hw_prof.phy_desc[i].sas_addr, pe->sas_addr, 912 SAS_ADDR_SIZE); 913 asd_ha->hw_prof.phy_desc[i].max_sas_lrate = 914 (pe->sas_link_rates & 0xF0) >> 4; 915 asd_ha->hw_prof.phy_desc[i].min_sas_lrate = 916 (pe->sas_link_rates & 0x0F); 917 asd_ha->hw_prof.phy_desc[i].max_sata_lrate = 918 (pe->sata_link_rates & 0xF0) >> 4; 919 asd_ha->hw_prof.phy_desc[i].min_sata_lrate = 920 (pe->sata_link_rates & 0x0F); 921 asd_ha->hw_prof.phy_desc[i].flags = pe->flags; 922 ASD_DPRINTK("ctrla: phy%d: sas_addr: %llx, sas rate:0x%x-0x%x," 923 " sata rate:0x%x-0x%x, flags:0x%x\n", 924 i, 925 SAS_ADDR(asd_ha->hw_prof.phy_desc[i].sas_addr), 926 asd_ha->hw_prof.phy_desc[i].max_sas_lrate, 927 asd_ha->hw_prof.phy_desc[i].min_sas_lrate, 928 asd_ha->hw_prof.phy_desc[i].max_sata_lrate, 929 asd_ha->hw_prof.phy_desc[i].min_sata_lrate, 930 asd_ha->hw_prof.phy_desc[i].flags); 931 } 932 933 return 0; 934} 935 936/** 937 * asd_process_ctrl_a_user - process CTRL-A user settings 938 * @asd_ha: pointer to the host adapter structure 939 * @flash_dir: pointer to the flash directory 940 */ 941static int asd_process_ctrl_a_user(struct asd_ha_struct *asd_ha, 942 struct asd_flash_dir *flash_dir) 943{ 944 int err, i; 945 u32 offs, size; 946 struct asd_ll_el *el; 947 struct asd_ctrla_phy_settings *ps; 948 struct asd_ctrla_phy_settings dflt_ps; 949 950 err = asd_find_flash_de(flash_dir, FLASH_DE_CTRL_A_USER, &offs, &size); 951 if (err) { 952 ASD_DPRINTK("couldn't find CTRL-A user settings section\n"); 953 ASD_DPRINTK("Creating default CTRL-A user settings section\n"); 954 955 dflt_ps.id0 = 'h'; 956 dflt_ps.num_phys = 8; 957 for (i =0; i < ASD_MAX_PHYS; i++) { 958 memcpy(dflt_ps.phy_ent[i].sas_addr, 959 asd_ha->hw_prof.sas_addr, SAS_ADDR_SIZE); 960 dflt_ps.phy_ent[i].sas_link_rates = 0x98; 961 dflt_ps.phy_ent[i].flags = 0x0; 962 dflt_ps.phy_ent[i].sata_link_rates = 0x0; 963 } 964 965 size = sizeof(struct asd_ctrla_phy_settings); 966 ps = &dflt_ps; 967 } 968 969 if (size == 0) 970 goto out; 971 972 err = -ENOMEM; 973 el = kmalloc(size, GFP_KERNEL); 974 if (!el) { 975 ASD_DPRINTK("no mem for ctrla user settings section\n"); 976 goto out; 977 } 978 979 err = asd_read_flash_seg(asd_ha, (void *)el, offs, size); 980 if (err) { 981 ASD_DPRINTK("couldn't read ctrla phy settings section\n"); 982 goto out2; 983 } 984 985 err = -ENOENT; 986 ps = asd_find_ll_by_id(el, 'h', 0xFF); 987 if (!ps) { 988 ASD_DPRINTK("couldn't find ctrla phy settings struct\n"); 989 goto out2; 990 } 991 992 err = asd_process_ctrla_phy_settings(asd_ha, ps); 993 if (err) { 994 ASD_DPRINTK("couldn't process ctrla phy settings\n"); 995 goto out2; 996 } 997out2: 998 kfree(el); 999out: 1000 return err; 1001} 1002 1003/** 1004 * asd_read_flash - read flash memory 1005 * @asd_ha: pointer to the host adapter structure 1006 */ 1007int asd_read_flash(struct asd_ha_struct *asd_ha) 1008{ 1009 int err; 1010 struct asd_flash_dir *flash_dir; 1011 1012 err = asd_flash_getid(asd_ha); 1013 if (err) 1014 return err; 1015 1016 flash_dir = kmalloc(sizeof(*flash_dir), GFP_KERNEL); 1017 if (!flash_dir) 1018 return -ENOMEM; 1019 1020 err = -ENOENT; 1021 if (!asd_find_flash_dir(asd_ha, flash_dir)) { 1022 ASD_DPRINTK("couldn't find flash directory\n"); 1023 goto out; 1024 } 1025 1026 if (le32_to_cpu(flash_dir->rev) != 2) { 1027 asd_printk("unsupported flash dir version:0x%x\n", 1028 le32_to_cpu(flash_dir->rev)); 1029 goto out; 1030 } 1031 1032 err = asd_process_ms(asd_ha, flash_dir); 1033 if (err) { 1034 ASD_DPRINTK("couldn't process manuf sector settings\n"); 1035 goto out; 1036 } 1037 1038 err = asd_process_ctrl_a_user(asd_ha, flash_dir); 1039 if (err) { 1040 ASD_DPRINTK("couldn't process CTRL-A user settings\n"); 1041 goto out; 1042 } 1043 1044out: 1045 kfree(flash_dir); 1046 return err; 1047} 1048