1*f11c7f63SJim Harris /*- 2*f11c7f63SJim Harris * BSD LICENSE 3*f11c7f63SJim Harris * 4*f11c7f63SJim Harris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved. 5*f11c7f63SJim Harris * All rights reserved. 6*f11c7f63SJim Harris * 7*f11c7f63SJim Harris * Redistribution and use in source and binary forms, with or without 8*f11c7f63SJim Harris * modification, are permitted provided that the following conditions 9*f11c7f63SJim Harris * are met: 10*f11c7f63SJim Harris * 11*f11c7f63SJim Harris * * Redistributions of source code must retain the above copyright 12*f11c7f63SJim Harris * notice, this list of conditions and the following disclaimer. 13*f11c7f63SJim Harris * * Redistributions in binary form must reproduce the above copyright 14*f11c7f63SJim Harris * notice, this list of conditions and the following disclaimer in 15*f11c7f63SJim Harris * the documentation and/or other materials provided with the 16*f11c7f63SJim Harris * distribution. 17*f11c7f63SJim Harris * 18*f11c7f63SJim Harris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19*f11c7f63SJim Harris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20*f11c7f63SJim Harris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21*f11c7f63SJim Harris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22*f11c7f63SJim Harris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23*f11c7f63SJim Harris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24*f11c7f63SJim Harris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25*f11c7f63SJim Harris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26*f11c7f63SJim Harris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27*f11c7f63SJim Harris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28*f11c7f63SJim Harris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29*f11c7f63SJim Harris */ 30*f11c7f63SJim Harris 31*f11c7f63SJim Harris #include <sys/cdefs.h> 32*f11c7f63SJim Harris __FBSDID("$FreeBSD$"); 33*f11c7f63SJim Harris 34*f11c7f63SJim Harris #include <dev/isci/isci.h> 35*f11c7f63SJim Harris #include <vm/vm.h> 36*f11c7f63SJim Harris #include <vm/pmap.h> 37*f11c7f63SJim Harris #include <machine/pmap.h> 38*f11c7f63SJim Harris #include <machine/vmparam.h> 39*f11c7f63SJim Harris #include <machine/pc/bios.h> 40*f11c7f63SJim Harris #include <dev/isci/scil/scu_bios_definitions.h> 41*f11c7f63SJim Harris 42*f11c7f63SJim Harris struct pcir_header 43*f11c7f63SJim Harris { 44*f11c7f63SJim Harris uint32_t signature; 45*f11c7f63SJim Harris uint16_t vendor_id; 46*f11c7f63SJim Harris uint16_t device_id; 47*f11c7f63SJim Harris uint16_t reserved; 48*f11c7f63SJim Harris uint16_t struct_length; 49*f11c7f63SJim Harris uint8_t struct_revision; 50*f11c7f63SJim Harris uint8_t cc_interface; 51*f11c7f63SJim Harris uint8_t cc_subclass; 52*f11c7f63SJim Harris uint8_t cc_baseclass; 53*f11c7f63SJim Harris uint16_t image_length; 54*f11c7f63SJim Harris uint16_t code_revision; 55*f11c7f63SJim Harris uint8_t code_type; 56*f11c7f63SJim Harris uint8_t indicator; 57*f11c7f63SJim Harris uint16_t reserved1; 58*f11c7f63SJim Harris }; 59*f11c7f63SJim Harris 60*f11c7f63SJim Harris struct rom_header 61*f11c7f63SJim Harris { 62*f11c7f63SJim Harris uint8_t signature_byte[2]; 63*f11c7f63SJim Harris uint8_t rom_length; 64*f11c7f63SJim Harris uint8_t jmp_code; 65*f11c7f63SJim Harris uint16_t entry_address; 66*f11c7f63SJim Harris uint8_t reserved[0x12]; 67*f11c7f63SJim Harris uint16_t pcir_pointer; 68*f11c7f63SJim Harris uint16_t pnp_pointer; 69*f11c7f63SJim Harris }; 70*f11c7f63SJim Harris 71*f11c7f63SJim Harris struct oem_parameters_table 72*f11c7f63SJim Harris { 73*f11c7f63SJim Harris uint8_t signature[4]; /* "$OEM" */ 74*f11c7f63SJim Harris struct revision 75*f11c7f63SJim Harris { 76*f11c7f63SJim Harris uint16_t major:8; /* bits [7:0] */ 77*f11c7f63SJim Harris uint16_t minor:8; /* bits [8:15] */ 78*f11c7f63SJim Harris } revision; 79*f11c7f63SJim Harris 80*f11c7f63SJim Harris uint16_t length; 81*f11c7f63SJim Harris uint8_t checksum; 82*f11c7f63SJim Harris uint8_t reserved1; 83*f11c7f63SJim Harris uint16_t reserved2; 84*f11c7f63SJim Harris uint8_t data[1]; 85*f11c7f63SJim Harris }; 86*f11c7f63SJim Harris 87*f11c7f63SJim Harris void 88*f11c7f63SJim Harris isci_get_oem_parameters(struct isci_softc *isci) 89*f11c7f63SJim Harris { 90*f11c7f63SJim Harris uint32_t OROM_PHYSICAL_ADDRESS_START = 0xC0000; 91*f11c7f63SJim Harris uint32_t OROM_SEARCH_LENGTH = 0x30000; 92*f11c7f63SJim Harris uint16_t OROM_SIGNATURE = 0xAA55; 93*f11c7f63SJim Harris uint32_t OROM_SIZE = 512; 94*f11c7f63SJim Harris uint8_t *orom_start = 95*f11c7f63SJim Harris (uint8_t *)BIOS_PADDRTOVADDR(OROM_PHYSICAL_ADDRESS_START); 96*f11c7f63SJim Harris uint32_t offset = 0; 97*f11c7f63SJim Harris 98*f11c7f63SJim Harris while (offset < OROM_SEARCH_LENGTH) { 99*f11c7f63SJim Harris 100*f11c7f63SJim Harris /* Look for the OROM signature at the beginning of every 101*f11c7f63SJim Harris * 512-byte block in the OROM region 102*f11c7f63SJim Harris */ 103*f11c7f63SJim Harris if (*(uint16_t*)(orom_start + offset) == OROM_SIGNATURE) { 104*f11c7f63SJim Harris uint32_t *rom; 105*f11c7f63SJim Harris struct rom_header *rom_header; 106*f11c7f63SJim Harris struct pcir_header *pcir_header; 107*f11c7f63SJim Harris uint16_t vendor_id = isci->pci_common_header.vendor_id; 108*f11c7f63SJim Harris uint16_t device_id = isci->pci_common_header.device_id; 109*f11c7f63SJim Harris 110*f11c7f63SJim Harris rom = (uint32_t *)(orom_start + offset); 111*f11c7f63SJim Harris rom_header = (struct rom_header *)rom; 112*f11c7f63SJim Harris pcir_header = (struct pcir_header *) 113*f11c7f63SJim Harris ((uint8_t*)rom + rom_header->pcir_pointer); 114*f11c7f63SJim Harris 115*f11c7f63SJim Harris /* OROM signature was found. Now check if the PCI 116*f11c7f63SJim Harris * device and vendor IDs match. 117*f11c7f63SJim Harris */ 118*f11c7f63SJim Harris if (pcir_header->vendor_id == vendor_id && 119*f11c7f63SJim Harris pcir_header->device_id == device_id) 120*f11c7f63SJim Harris { 121*f11c7f63SJim Harris /* OROM for this PCI device was found. Search 122*f11c7f63SJim Harris * this 512-byte block for the $OEM string, 123*f11c7f63SJim Harris * which will mark the beginning of the OEM 124*f11c7f63SJim Harris * parameter block. 125*f11c7f63SJim Harris */ 126*f11c7f63SJim Harris uint8_t oem_sig[4] = {'$', 'O', 'E', 'M'}; 127*f11c7f63SJim Harris int dword_index; 128*f11c7f63SJim Harris 129*f11c7f63SJim Harris for (dword_index = 0; 130*f11c7f63SJim Harris dword_index < OROM_SIZE/sizeof(uint32_t); 131*f11c7f63SJim Harris dword_index++) 132*f11c7f63SJim Harris if (rom[dword_index] == *(uint32_t *)oem_sig) { 133*f11c7f63SJim Harris /* $OEM signature string was found. Now copy the OEM parameter block 134*f11c7f63SJim Harris * into the struct ISCI_CONTROLLER objects. After the controllers are 135*f11c7f63SJim Harris * constructed, we will pass this OEM parameter data to the SCI core 136*f11c7f63SJim Harris * controller. 137*f11c7f63SJim Harris */ 138*f11c7f63SJim Harris struct oem_parameters_table *oem = 139*f11c7f63SJim Harris (struct oem_parameters_table *)&rom[dword_index]; 140*f11c7f63SJim Harris SCI_BIOS_OEM_PARAM_BLOCK_T *oem_data = 141*f11c7f63SJim Harris (SCI_BIOS_OEM_PARAM_BLOCK_T *)oem->data; 142*f11c7f63SJim Harris int index; 143*f11c7f63SJim Harris 144*f11c7f63SJim Harris isci->oem_parameters_found = TRUE; 145*f11c7f63SJim Harris isci_log_message(1, "ISCI", "oem_data->header.num_elements = %d\n", 146*f11c7f63SJim Harris oem_data->header.num_elements); 147*f11c7f63SJim Harris 148*f11c7f63SJim Harris for (index = 0; index < oem_data->header.num_elements; index++) 149*f11c7f63SJim Harris { 150*f11c7f63SJim Harris memcpy(&isci->controllers[index].oem_parameters.sds1, 151*f11c7f63SJim Harris &oem_data->controller_element[index], 152*f11c7f63SJim Harris sizeof(SCIC_SDS_OEM_PARAMETERS_T)); 153*f11c7f63SJim Harris 154*f11c7f63SJim Harris isci_log_message(1, "ISCI", "OEM Parameter Data for controller %d\n", 155*f11c7f63SJim Harris index); 156*f11c7f63SJim Harris 157*f11c7f63SJim Harris for (int i = 0; i < sizeof(SCIC_SDS_OEM_PARAMETERS_T); i++) { 158*f11c7f63SJim Harris uint8_t val = ((uint8_t *)&oem_data->controller_element[index])[i]; 159*f11c7f63SJim Harris isci_log_message(1, "ISCI", "%02x ", val); 160*f11c7f63SJim Harris } 161*f11c7f63SJim Harris isci_log_message(1, "ISCI", "\n"); 162*f11c7f63SJim Harris isci->controllers[index].oem_parameters_version = oem_data->header.version; 163*f11c7f63SJim Harris } 164*f11c7f63SJim Harris } 165*f11c7f63SJim Harris 166*f11c7f63SJim Harris /* No need to continue searching for another 167*f11c7f63SJim Harris * OROM that matches this PCI device, so return 168*f11c7f63SJim Harris * immediately. 169*f11c7f63SJim Harris */ 170*f11c7f63SJim Harris return; 171*f11c7f63SJim Harris } 172*f11c7f63SJim Harris } 173*f11c7f63SJim Harris 174*f11c7f63SJim Harris offset += OROM_SIZE; 175*f11c7f63SJim Harris } 176*f11c7f63SJim Harris } 177