189857Sobrien/*- 280016Sobrien * BSD LICENSE 389857Sobrien * 489857Sobrien * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 580016Sobrien * All rights reserved. 689857Sobrien * 778828Sobrien * Redistribution and use in source and binary forms, with or without 889857Sobrien * modification, are permitted provided that the following conditions 989857Sobrien * are met: 1078828Sobrien * 1189857Sobrien * * Redistributions of source code must retain the above copyright 1278828Sobrien * notice, this list of conditions and the following disclaimer. 1389857Sobrien * * Redistributions in binary form must reproduce the above copyright 1489857Sobrien * notice, this list of conditions and the following disclaimer in 1589857Sobrien * the documentation and/or other materials provided with the 1689857Sobrien * distribution. 1789857Sobrien * 1889857Sobrien * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1989857Sobrien * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2089857Sobrien * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2189857Sobrien * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2289857Sobrien * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2389857Sobrien * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2489857Sobrien * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2589857Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2689857Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2789857Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2889857Sobrien * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2989857Sobrien */ 3089857Sobrien 3189857Sobrien#include <sys/cdefs.h> 3289857Sobrien__FBSDID("$FreeBSD: releng/10.2/sys/dev/isci/isci_oem_parameters.c 231136 2012-02-07 17:43:58Z jimharris $"); 3389857Sobrien 3489857Sobrien#include <dev/isci/isci.h> 3589857Sobrien#include <vm/vm.h> 3689857Sobrien#include <vm/pmap.h> 3789857Sobrien#include <machine/pmap.h> 3889857Sobrien#include <machine/vmparam.h> 3989857Sobrien#include <machine/pc/bios.h> 4089857Sobrien#include <dev/isci/scil/scu_bios_definitions.h> 4189857Sobrien 4289857Sobrienstruct pcir_header 4389857Sobrien{ 4489857Sobrien uint32_t signature; 4589857Sobrien uint16_t vendor_id; 4689857Sobrien uint16_t device_id; 4789857Sobrien uint16_t reserved; 4889857Sobrien uint16_t struct_length; 4989857Sobrien uint8_t struct_revision; 5089857Sobrien uint8_t cc_interface; 5189857Sobrien uint8_t cc_subclass; 5289857Sobrien uint8_t cc_baseclass; 5389857Sobrien uint16_t image_length; 5489857Sobrien uint16_t code_revision; 5589857Sobrien uint8_t code_type; 5689857Sobrien uint8_t indicator; 5789857Sobrien uint16_t reserved1; 5889857Sobrien}; 5989857Sobrien 6089857Sobrienstruct rom_header 6189857Sobrien{ 6289857Sobrien uint8_t signature_byte[2]; 6389857Sobrien uint8_t rom_length; 6489857Sobrien uint8_t jmp_code; 6589857Sobrien uint16_t entry_address; 6689857Sobrien uint8_t reserved[0x12]; 6789857Sobrien uint16_t pcir_pointer; 6889857Sobrien uint16_t pnp_pointer; 6989857Sobrien}; 7089857Sobrien 7189857Sobrienstruct oem_parameters_table 7289857Sobrien{ 7389857Sobrien uint8_t signature[4]; /* "$OEM" */ 7489857Sobrien struct revision 7589857Sobrien { 7689857Sobrien uint16_t major:8; /* bits [7:0] */ 7789857Sobrien uint16_t minor:8; /* bits [8:15] */ 7889857Sobrien } revision; 7989857Sobrien 8089857Sobrien uint16_t length; 8189857Sobrien uint8_t checksum; 8289857Sobrien uint8_t reserved1; 8389857Sobrien uint16_t reserved2; 8489857Sobrien uint8_t data[1]; 8589857Sobrien}; 8689857Sobrien 8789857Sobrienvoid 8889857Sobrienisci_get_oem_parameters(struct isci_softc *isci) 8989857Sobrien{ 9089857Sobrien uint32_t OROM_PHYSICAL_ADDRESS_START = 0xC0000; 9189857Sobrien uint32_t OROM_SEARCH_LENGTH = 0x30000; 9289857Sobrien uint16_t OROM_SIGNATURE = 0xAA55; 9389857Sobrien uint32_t OROM_SIZE = 512; 9489857Sobrien uint8_t *orom_start = 9589857Sobrien (uint8_t *)BIOS_PADDRTOVADDR(OROM_PHYSICAL_ADDRESS_START); 9689857Sobrien uint32_t offset = 0; 9789857Sobrien 9889857Sobrien while (offset < OROM_SEARCH_LENGTH) { 9989857Sobrien 10089857Sobrien /* Look for the OROM signature at the beginning of every 10189857Sobrien * 512-byte block in the OROM region 10289857Sobrien */ 10389857Sobrien if (*(uint16_t*)(orom_start + offset) == OROM_SIGNATURE) { 10489857Sobrien uint32_t *rom; 10589857Sobrien struct rom_header *rom_header; 10689857Sobrien struct pcir_header *pcir_header; 10789857Sobrien uint16_t vendor_id = isci->pci_common_header.vendor_id; 10889857Sobrien uint16_t device_id = isci->pci_common_header.device_id; 10989857Sobrien 11089857Sobrien rom = (uint32_t *)(orom_start + offset); 11189857Sobrien rom_header = (struct rom_header *)rom; 11289857Sobrien pcir_header = (struct pcir_header *) 11389857Sobrien ((uint8_t*)rom + rom_header->pcir_pointer); 11489857Sobrien 11589857Sobrien /* OROM signature was found. Now check if the PCI 11689857Sobrien * device and vendor IDs match. 11789857Sobrien */ 11889857Sobrien if (pcir_header->vendor_id == vendor_id && 11989857Sobrien pcir_header->device_id == device_id) 12089857Sobrien { 12189857Sobrien /* OROM for this PCI device was found. Search 12289857Sobrien * this 512-byte block for the $OEM string, 12389857Sobrien * which will mark the beginning of the OEM 12489857Sobrien * parameter block. 12589857Sobrien */ 12689857Sobrien uint8_t oem_sig[4] = {'$', 'O', 'E', 'M'}; 12789857Sobrien int dword_index; 12889857Sobrien 12989857Sobrien for (dword_index = 0; 13089857Sobrien dword_index < OROM_SIZE/sizeof(uint32_t); 13189857Sobrien dword_index++) 13289857Sobrien if (rom[dword_index] == *(uint32_t *)oem_sig) { 13389857Sobrien /* $OEM signature string was found. Now copy the OEM parameter block 13489857Sobrien * into the struct ISCI_CONTROLLER objects. After the controllers are 13589857Sobrien * constructed, we will pass this OEM parameter data to the SCI core 13689857Sobrien * controller. 13789857Sobrien */ 13889857Sobrien struct oem_parameters_table *oem = 13989857Sobrien (struct oem_parameters_table *)&rom[dword_index]; 14089857Sobrien SCI_BIOS_OEM_PARAM_BLOCK_T *oem_data = 14189857Sobrien (SCI_BIOS_OEM_PARAM_BLOCK_T *)oem->data; 14289857Sobrien int index; 14389857Sobrien 14489857Sobrien isci->oem_parameters_found = TRUE; 14589857Sobrien isci_log_message(1, "ISCI", "oem_data->header.num_elements = %d\n", 14689857Sobrien oem_data->header.num_elements); 14789857Sobrien 14889857Sobrien for (index = 0; index < oem_data->header.num_elements; index++) 14989857Sobrien { 15089857Sobrien memcpy(&isci->controllers[index].oem_parameters.sds1, 15189857Sobrien &oem_data->controller_element[index], 15289857Sobrien sizeof(SCIC_SDS_OEM_PARAMETERS_T)); 15389857Sobrien 15489857Sobrien isci_log_message(1, "ISCI", "OEM Parameter Data for controller %d\n", 15589857Sobrien index); 15689857Sobrien 15789857Sobrien for (int i = 0; i < sizeof(SCIC_SDS_OEM_PARAMETERS_T); i++) { 15889857Sobrien uint8_t val = ((uint8_t *)&oem_data->controller_element[index])[i]; 15989857Sobrien isci_log_message(1, "ISCI", "%02x ", val); 16089857Sobrien } 16189857Sobrien isci_log_message(1, "ISCI", "\n"); 16289857Sobrien isci->controllers[index].oem_parameters_version = oem_data->header.version; 16389857Sobrien } 16489857Sobrien } 16589857Sobrien 16689857Sobrien /* No need to continue searching for another 16789857Sobrien * OROM that matches this PCI device, so return 16889857Sobrien * immediately. 16989857Sobrien */ 17089857Sobrien return; 17189857Sobrien } 17289857Sobrien } 17389857Sobrien 17489857Sobrien offset += OROM_SIZE; 17589857Sobrien } 17689857Sobrien} 17789857Sobrien