10db7e66cSJonathan Chen /* 20db7e66cSJonathan Chen * Copyright (c) 2000,2001 Jonathan Chen. 30db7e66cSJonathan Chen * All rights reserved. 40db7e66cSJonathan Chen * 50db7e66cSJonathan Chen * Redistribution and use in source and binary forms, with or without 60db7e66cSJonathan Chen * modification, are permitted provided that the following conditions 70db7e66cSJonathan Chen * are met: 80db7e66cSJonathan Chen * 1. Redistributions of source code must retain the above copyright 90db7e66cSJonathan Chen * notice, this list of conditions, and the following disclaimer, 100db7e66cSJonathan Chen * without modification, immediately at the beginning of the file. 110db7e66cSJonathan Chen * 2. Redistributions in binary form must reproduce the above copyright 120db7e66cSJonathan Chen * notice, this list of conditions and the following disclaimer in 130db7e66cSJonathan Chen * the documentation and/or other materials provided with the 140db7e66cSJonathan Chen * distribution. 150db7e66cSJonathan Chen * 160db7e66cSJonathan Chen * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 170db7e66cSJonathan Chen * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 180db7e66cSJonathan Chen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 190db7e66cSJonathan Chen * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 200db7e66cSJonathan Chen * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 210db7e66cSJonathan Chen * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 220db7e66cSJonathan Chen * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 230db7e66cSJonathan Chen * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 240db7e66cSJonathan Chen * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 250db7e66cSJonathan Chen * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 260db7e66cSJonathan Chen * SUCH DAMAGE. 270db7e66cSJonathan Chen * 280db7e66cSJonathan Chen * $FreeBSD$ 290db7e66cSJonathan Chen */ 300db7e66cSJonathan Chen 310db7e66cSJonathan Chen /* 320db7e66cSJonathan Chen * CIS Handling for the Cardbus Bus 330db7e66cSJonathan Chen */ 340db7e66cSJonathan Chen 350db7e66cSJonathan Chen #define CARDBUS_DEBUG 360db7e66cSJonathan Chen 370db7e66cSJonathan Chen #include <sys/param.h> 380db7e66cSJonathan Chen #include <sys/systm.h> 390db7e66cSJonathan Chen #include <sys/kernel.h> 400db7e66cSJonathan Chen 410db7e66cSJonathan Chen #include <sys/bus.h> 420db7e66cSJonathan Chen #include <machine/bus.h> 430db7e66cSJonathan Chen #include <machine/resource.h> 440db7e66cSJonathan Chen #include <sys/rman.h> 450db7e66cSJonathan Chen 460db7e66cSJonathan Chen #include <pci/pcivar.h> 470db7e66cSJonathan Chen 480db7e66cSJonathan Chen #include <dev/cardbus/cardbusreg.h> 490db7e66cSJonathan Chen #include <dev/cardbus/cardbus_cis.h> 500db7e66cSJonathan Chen 510db7e66cSJonathan Chen #include "pccbb_if.h" 520db7e66cSJonathan Chen 530db7e66cSJonathan Chen #if defined CARDBUS_DEBUG 540db7e66cSJonathan Chen #define STATIC 550db7e66cSJonathan Chen #define DPRINTF(a) printf a 560db7e66cSJonathan Chen #define DEVPRINTF(x) device_printf x 570db7e66cSJonathan Chen #else 580db7e66cSJonathan Chen #define STATIC static 590db7e66cSJonathan Chen #define DPRINTF(a) 600db7e66cSJonathan Chen #define DEVPRINTF(x) 610db7e66cSJonathan Chen #endif 620db7e66cSJonathan Chen 630db7e66cSJonathan Chen #if !defined(lint) 640db7e66cSJonathan Chen static const char rcsid[] = 650db7e66cSJonathan Chen "$FreeBSD$"; 660db7e66cSJonathan Chen #endif 670db7e66cSJonathan Chen 680db7e66cSJonathan Chen struct tupleinfo; 690db7e66cSJonathan Chen 700db7e66cSJonathan Chen static int decode_tuples(device_t dev, device_t child, 710db7e66cSJonathan Chen u_int8_t *tuples, int len); 720db7e66cSJonathan Chen static int cardbus_read_exrom_cis(device_t dev, struct resource *res, 730db7e66cSJonathan Chen int cis, u_int8_t* tuple, int len); 740db7e66cSJonathan Chen static int cardbus_read_tuples_conf(device_t dev, device_t child, 750db7e66cSJonathan Chen u_int32_t cis_ptr, u_int8_t *tuples, 760db7e66cSJonathan Chen int len); 770db7e66cSJonathan Chen static int cardbus_read_tuples_mem(device_t dev, device_t child, int space, 780db7e66cSJonathan Chen u_int32_t cis_ptr, u_int8_t *tuples, 790db7e66cSJonathan Chen int len); 800db7e66cSJonathan Chen static int cardbus_read_tuples(device_t dev, device_t child, u_int8_t *tuples, 810db7e66cSJonathan Chen int len); 820db7e66cSJonathan Chen 830db7e66cSJonathan Chen #define DECODE_PROTOTYPE(NAME) static int decode_tuple_ ## NAME \ 840db7e66cSJonathan Chen (device_t dev, device_t child, int id, int len, \ 850db7e66cSJonathan Chen u_int8_t *buff, struct tupleinfo *info) 860db7e66cSJonathan Chen DECODE_PROTOTYPE(generic); 870db7e66cSJonathan Chen DECODE_PROTOTYPE(bar); 880db7e66cSJonathan Chen DECODE_PROTOTYPE(linktarget); 890db7e66cSJonathan Chen DECODE_PROTOTYPE(vers_1); 900db7e66cSJonathan Chen DECODE_PROTOTYPE(manfid); 910db7e66cSJonathan Chen DECODE_PROTOTYPE(funcid); 920db7e66cSJonathan Chen DECODE_PROTOTYPE(funce); 930db7e66cSJonathan Chen DECODE_PROTOTYPE(end); 940db7e66cSJonathan Chen DECODE_PROTOTYPE(unhandled); 950db7e66cSJonathan Chen 960db7e66cSJonathan Chen static struct tupleinfo { 970db7e66cSJonathan Chen u_int8_t id; 980db7e66cSJonathan Chen char* name; 990db7e66cSJonathan Chen int (*func)(device_t dev, device_t child, int id, int len, 1000db7e66cSJonathan Chen u_int8_t *buff, struct tupleinfo *info); 1010db7e66cSJonathan Chen } tupleinfo[] = { 1020db7e66cSJonathan Chen #define MAKETUPLE(NAME,FUNC) { CISTPL_ ## NAME, #NAME, decode_tuple_ ## FUNC } 1030db7e66cSJonathan Chen MAKETUPLE(NULL, generic), 1040db7e66cSJonathan Chen MAKETUPLE(DEVICE, generic), 1050db7e66cSJonathan Chen MAKETUPLE(LONG_LINK_CB, unhandled), 1060db7e66cSJonathan Chen MAKETUPLE(INDIRECT, unhandled), 1070db7e66cSJonathan Chen MAKETUPLE(CONFIG_CB, generic), 1080db7e66cSJonathan Chen MAKETUPLE(CFTABLE_ENTRY_CB, generic), 1090db7e66cSJonathan Chen MAKETUPLE(LONGLINK_MFC, unhandled), 1100db7e66cSJonathan Chen MAKETUPLE(BAR, bar), 1110db7e66cSJonathan Chen MAKETUPLE(PWR_MGMNT, generic), 1120db7e66cSJonathan Chen MAKETUPLE(EXTDEVICE, generic), 1130db7e66cSJonathan Chen MAKETUPLE(CHECKSUM, generic), 1140db7e66cSJonathan Chen MAKETUPLE(LONGLINK_A, unhandled), 1150db7e66cSJonathan Chen MAKETUPLE(LONGLINK_C, unhandled), 1160db7e66cSJonathan Chen MAKETUPLE(LINKTARGET, linktarget), 1170db7e66cSJonathan Chen MAKETUPLE(NO_LINK, generic), 1180db7e66cSJonathan Chen MAKETUPLE(VERS_1, vers_1), 1190db7e66cSJonathan Chen MAKETUPLE(ALTSTR, generic), 1200db7e66cSJonathan Chen MAKETUPLE(DEVICE_A, generic), 1210db7e66cSJonathan Chen MAKETUPLE(JEDEC_C, generic), 1220db7e66cSJonathan Chen MAKETUPLE(JEDEC_A, generic), 1230db7e66cSJonathan Chen MAKETUPLE(CONFIG, generic), 1240db7e66cSJonathan Chen MAKETUPLE(CFTABLE_ENTRY, generic), 1250db7e66cSJonathan Chen MAKETUPLE(DEVICE_OC, generic), 1260db7e66cSJonathan Chen MAKETUPLE(DEVICE_OA, generic), 1270db7e66cSJonathan Chen MAKETUPLE(DEVICE_GEO, generic), 1280db7e66cSJonathan Chen MAKETUPLE(DEVICE_GEO_A, generic), 1290db7e66cSJonathan Chen MAKETUPLE(MANFID, manfid), 1300db7e66cSJonathan Chen MAKETUPLE(FUNCID, funcid), 1310db7e66cSJonathan Chen MAKETUPLE(FUNCE, funce), 1320db7e66cSJonathan Chen MAKETUPLE(SWIL, generic), 1330db7e66cSJonathan Chen MAKETUPLE(VERS_2, generic), 1340db7e66cSJonathan Chen MAKETUPLE(FORMAT, generic), 1350db7e66cSJonathan Chen MAKETUPLE(GEOMETRY, generic), 1360db7e66cSJonathan Chen MAKETUPLE(BYTEORDER, generic), 1370db7e66cSJonathan Chen MAKETUPLE(DATE, generic), 1380db7e66cSJonathan Chen MAKETUPLE(BATTERY, generic), 1390db7e66cSJonathan Chen MAKETUPLE(ORG, generic), 1400db7e66cSJonathan Chen MAKETUPLE(END, end), 1410db7e66cSJonathan Chen #undef MAKETUPLE 1420db7e66cSJonathan Chen }; 1430db7e66cSJonathan Chen 1440db7e66cSJonathan Chen static char* funcnames[] = { 1450db7e66cSJonathan Chen "Multi-Functioned", 1460db7e66cSJonathan Chen "Memory", 1470db7e66cSJonathan Chen "Serial Port", 1480db7e66cSJonathan Chen "Parallel Port", 1490db7e66cSJonathan Chen "Fixed Disk", 1500db7e66cSJonathan Chen "Video Adaptor", 1510db7e66cSJonathan Chen "Network Adaptor", 1520db7e66cSJonathan Chen "AIMS", 1530db7e66cSJonathan Chen "SCSI", 1540db7e66cSJonathan Chen "Security" 1550db7e66cSJonathan Chen }; 1560db7e66cSJonathan Chen 1570db7e66cSJonathan Chen DECODE_PROTOTYPE(generic) 1580db7e66cSJonathan Chen { 1590db7e66cSJonathan Chen #ifdef CARDBUS_DEBUG 1600db7e66cSJonathan Chen int i; 1610db7e66cSJonathan Chen 1620db7e66cSJonathan Chen if (info) 1630db7e66cSJonathan Chen printf ("TUPLE: %s [%d]:", info->name, len); 1640db7e66cSJonathan Chen else 1650db7e66cSJonathan Chen printf ("TUPLE: Unknown(0x%02x) [%d]:", id, len); 1660db7e66cSJonathan Chen 1670db7e66cSJonathan Chen for (i = 0; i < len; i++) { 1680db7e66cSJonathan Chen if (i % 0x10 == 0 && len > 0x10) 1690db7e66cSJonathan Chen printf ("\n 0x%02x:", i); 1700db7e66cSJonathan Chen printf (" %02x", buff[i]); 1710db7e66cSJonathan Chen } 1720db7e66cSJonathan Chen printf ("\n"); 1730db7e66cSJonathan Chen #endif 1740db7e66cSJonathan Chen return 0; 1750db7e66cSJonathan Chen } 1760db7e66cSJonathan Chen 1770db7e66cSJonathan Chen DECODE_PROTOTYPE(linktarget) 1780db7e66cSJonathan Chen { 1790db7e66cSJonathan Chen if (len != 3 || buff[0] != 'C' || buff[1] != 'I' || buff[2] != 'S') { 1800db7e66cSJonathan Chen printf("Invalid data for CIS Link Target!\n"); 1810db7e66cSJonathan Chen decode_tuple_generic(dev, child, id, len, buff, info); 1820db7e66cSJonathan Chen return EINVAL; 1830db7e66cSJonathan Chen } 1840db7e66cSJonathan Chen return 0; 1850db7e66cSJonathan Chen } 1860db7e66cSJonathan Chen 1870db7e66cSJonathan Chen DECODE_PROTOTYPE(vers_1) 1880db7e66cSJonathan Chen { 1890db7e66cSJonathan Chen int i; 1900db7e66cSJonathan Chen printf("Product version: %d.%d\n", buff[0], buff[1]); 1910db7e66cSJonathan Chen printf("Product name: "); 1920db7e66cSJonathan Chen for (i = 2; i < len; i++) { 1930db7e66cSJonathan Chen if (buff[i] == '\0') 1940db7e66cSJonathan Chen printf (" | "); 1950db7e66cSJonathan Chen else if (buff[i] == 0xff) 1960db7e66cSJonathan Chen break; 1970db7e66cSJonathan Chen else 1980db7e66cSJonathan Chen printf("%c", buff[i]); 1990db7e66cSJonathan Chen } 2000db7e66cSJonathan Chen printf("\n"); 2010db7e66cSJonathan Chen return 0; 2020db7e66cSJonathan Chen } 2030db7e66cSJonathan Chen 2040db7e66cSJonathan Chen DECODE_PROTOTYPE(funcid) 2050db7e66cSJonathan Chen { 2060db7e66cSJonathan Chen int i; 2070db7e66cSJonathan Chen int numnames = sizeof(funcnames)/sizeof(funcnames[0]); 2080db7e66cSJonathan Chen 2090db7e66cSJonathan Chen printf("Functions: "); 2100db7e66cSJonathan Chen for(i = 0; i < len; i++) { 2110db7e66cSJonathan Chen if (buff[i] < numnames) 2120db7e66cSJonathan Chen printf ("%s", funcnames[buff[i]]); 2130db7e66cSJonathan Chen else 2140db7e66cSJonathan Chen printf ("Unknown(%d)", buff[i]); 2150db7e66cSJonathan Chen if (i < len-1) printf(", "); 2160db7e66cSJonathan Chen } 2170db7e66cSJonathan Chen printf ("\n"); 2180db7e66cSJonathan Chen return 0; 2190db7e66cSJonathan Chen } 2200db7e66cSJonathan Chen 2210db7e66cSJonathan Chen DECODE_PROTOTYPE(manfid) 2220db7e66cSJonathan Chen { 2230db7e66cSJonathan Chen int i; 2240db7e66cSJonathan Chen printf ("Manufacturer ID: "); 2250db7e66cSJonathan Chen for (i = 0; i < len; i++) 2260db7e66cSJonathan Chen printf("%02x", buff[i]); 2270db7e66cSJonathan Chen printf("\n"); 2280db7e66cSJonathan Chen return 0; 2290db7e66cSJonathan Chen } 2300db7e66cSJonathan Chen 2310db7e66cSJonathan Chen DECODE_PROTOTYPE(funce) 2320db7e66cSJonathan Chen { 2330db7e66cSJonathan Chen int i; 2340db7e66cSJonathan Chen printf ("Function Extension: "); 2350db7e66cSJonathan Chen for (i = 0; i < len; i++) 2360db7e66cSJonathan Chen printf("%02x", buff[i]); 2370db7e66cSJonathan Chen printf("\n"); 2380db7e66cSJonathan Chen return 0; 2390db7e66cSJonathan Chen } 2400db7e66cSJonathan Chen 2410db7e66cSJonathan Chen DECODE_PROTOTYPE(bar) 2420db7e66cSJonathan Chen { 2430db7e66cSJonathan Chen if (len != 6) { 2440db7e66cSJonathan Chen printf ("*** ERROR *** BAR length not 6 (%d)\n", len); 2450db7e66cSJonathan Chen return EINVAL; 2460db7e66cSJonathan Chen } else { 2470db7e66cSJonathan Chen int type; 2480db7e66cSJonathan Chen int reg; 2490db7e66cSJonathan Chen u_int32_t bar; 2500db7e66cSJonathan Chen u_int32_t start, len; 2510db7e66cSJonathan Chen struct resource *res; 2520db7e66cSJonathan Chen 2530db7e66cSJonathan Chen reg = *(u_int16_t*)buff; 2540db7e66cSJonathan Chen len = *(u_int32_t*)(buff+2); 2550db7e66cSJonathan Chen if (reg & TPL_BAR_REG_AS) { 2560db7e66cSJonathan Chen type = SYS_RES_IOPORT; 2570db7e66cSJonathan Chen } else { 2580db7e66cSJonathan Chen type = SYS_RES_MEMORY; 2590db7e66cSJonathan Chen } 2600db7e66cSJonathan Chen bar = (reg & TPL_BAR_REG_ASI_MASK) - 1; 2610db7e66cSJonathan Chen if (bar < 0 || bar > 6) { 2620db7e66cSJonathan Chen device_printf(dev, "Invalid BAR number: %02x(%02x)\n", 2630db7e66cSJonathan Chen reg, bar); 2640db7e66cSJonathan Chen return EINVAL; 2650db7e66cSJonathan Chen } 2660db7e66cSJonathan Chen bar = CARDBUS_BASE0_REG + bar * 4; 2670db7e66cSJonathan Chen DEVPRINTF((dev, "Opening BAR: type=%s, bar=%02x, len=%04x\n", 2680db7e66cSJonathan Chen (type==SYS_RES_MEMORY)?"MEM":"IO", bar, len)); 2690db7e66cSJonathan Chen res = bus_generic_alloc_resource(child, child, type, ®, 0, 2700db7e66cSJonathan Chen ~0, len, rman_make_alignment_flags(len) | RF_ACTIVE); 2710db7e66cSJonathan Chen if (res == NULL) { 2720db7e66cSJonathan Chen device_printf(dev, "Cannot allocate BAR %02x\n", reg); 2730db7e66cSJonathan Chen } else { 2740db7e66cSJonathan Chen start = rman_get_start(res); 2750db7e66cSJonathan Chen if (reg == CARDBUS_ROM_REG) start |= 1; 2760db7e66cSJonathan Chen pci_write_config(child, reg, start, 4); 2770db7e66cSJonathan Chen } 2780db7e66cSJonathan Chen } 2790db7e66cSJonathan Chen return 0; 2800db7e66cSJonathan Chen } 2810db7e66cSJonathan Chen 2820db7e66cSJonathan Chen DECODE_PROTOTYPE(unhandled) 2830db7e66cSJonathan Chen { 2840db7e66cSJonathan Chen printf ("TUPLE: %s [%d] is unhandled! Bailing...", info->name, len); 2850db7e66cSJonathan Chen return -1; 2860db7e66cSJonathan Chen } 2870db7e66cSJonathan Chen 2880db7e66cSJonathan Chen DECODE_PROTOTYPE(end) 2890db7e66cSJonathan Chen { 2900db7e66cSJonathan Chen return -1; 2910db7e66cSJonathan Chen } 2920db7e66cSJonathan Chen 2930db7e66cSJonathan Chen static int decode_tuples(device_t dev, device_t child, 2940db7e66cSJonathan Chen u_int8_t *tuples, int len) 2950db7e66cSJonathan Chen { 2960db7e66cSJonathan Chen int ret = 0; 2970db7e66cSJonathan Chen if (CISTPL_LINKTARGET != *tuples) { 2980db7e66cSJonathan Chen device_printf(dev, "CIS does not start with link target\n"); 2990db7e66cSJonathan Chen return EINVAL; 3000db7e66cSJonathan Chen } 3010db7e66cSJonathan Chen do { 3020db7e66cSJonathan Chen int i; 3030db7e66cSJonathan Chen int numtupleids = sizeof(tupleinfo)/sizeof(tupleinfo[0]); 3040db7e66cSJonathan Chen for (i = 0; i < numtupleids; i++) { 3050db7e66cSJonathan Chen if (tuples[0] == tupleinfo[i].id) { 3060db7e66cSJonathan Chen ret = tupleinfo[i].func(dev, child, tuples[0], 3070db7e66cSJonathan Chen tuples[1], tuples+2, 3080db7e66cSJonathan Chen &tupleinfo[i]); 3090db7e66cSJonathan Chen break; 3100db7e66cSJonathan Chen } 3110db7e66cSJonathan Chen } 3120db7e66cSJonathan Chen if (i == numtupleids) 3130db7e66cSJonathan Chen ret = decode_tuple_generic(dev, child, tuples[0], 3140db7e66cSJonathan Chen tuples[1], tuples+2, NULL); 3150db7e66cSJonathan Chen 3160db7e66cSJonathan Chen len -= (tuples[1]+2); 3170db7e66cSJonathan Chen tuples += tuples[1]+2; 3180db7e66cSJonathan Chen } while (len > 0 && ret == 0); 3190db7e66cSJonathan Chen 3200db7e66cSJonathan Chen if (ret < 0) return 0; 3210db7e66cSJonathan Chen else if (ret != 0) return ret; 3220db7e66cSJonathan Chen else { 3230db7e66cSJonathan Chen device_printf(dev, "CIS too long or END not encountered!\n"); 3240db7e66cSJonathan Chen return EFBIG; 3250db7e66cSJonathan Chen } 3260db7e66cSJonathan Chen } 3270db7e66cSJonathan Chen 3280db7e66cSJonathan Chen static int 3290db7e66cSJonathan Chen cardbus_read_exrom_cis(device_t dev, struct resource *res, int cis, 3300db7e66cSJonathan Chen u_int8_t* tuple, int len) 3310db7e66cSJonathan Chen { 3320db7e66cSJonathan Chen #define READROM(rom, type, offset) \ 3330db7e66cSJonathan Chen (*((u_int ## type ##_t *)(((unsigned char*)rom) + offset))) 3340db7e66cSJonathan Chen 3350db7e66cSJonathan Chen u_int32_t addr = 0; /* offset of current rom image */ 3360db7e66cSJonathan Chen int romnum = 0; 3370db7e66cSJonathan Chen unsigned char *data; 3380db7e66cSJonathan Chen u_int32_t imagesize; 3390db7e66cSJonathan Chen unsigned char *image; 3400db7e66cSJonathan Chen int imagenum; 3410db7e66cSJonathan Chen 3420db7e66cSJonathan Chen image = (unsigned char*)rman_get_virtual(res); 3430db7e66cSJonathan Chen imagenum = CARDBUS_CIS_ASI_ROM_IMAGE(cis); 3440db7e66cSJonathan Chen do { 3450db7e66cSJonathan Chen if (READROM(image, 16, CARDBUS_EXROM_SIGNATURE) != 0xaa55) { 3460db7e66cSJonathan Chen device_printf (dev, "Bad header in rom %d: %04x\n", 3470db7e66cSJonathan Chen romnum, *(u_int16_t*)(image + 3480db7e66cSJonathan Chen CARDBUS_EXROM_SIGNATURE)); 3490db7e66cSJonathan Chen return ENXIO; 3500db7e66cSJonathan Chen } 3510db7e66cSJonathan Chen data = image + READROM(image, 16, CARDBUS_EXROM_DATA_PTR); 3520db7e66cSJonathan Chen imagesize = READROM(data, 16, CARDBUS_EXROM_DATA_IMAGE_LENGTH); 3530db7e66cSJonathan Chen 3540db7e66cSJonathan Chen if(imagesize == 0) 3550db7e66cSJonathan Chen /* 3560db7e66cSJonathan Chen * XXX some ROMs seem to have this as zero, 3570db7e66cSJonathan Chen * can we assume this means 1 block? 3580db7e66cSJonathan Chen */ 3590db7e66cSJonathan Chen imagesize = 1; 3600db7e66cSJonathan Chen imagesize <<= 9; 3610db7e66cSJonathan Chen 3620db7e66cSJonathan Chen if (imagenum == romnum) { 3630db7e66cSJonathan Chen romnum = -1; 3640db7e66cSJonathan Chen memcpy(tuple, image+CARDBUS_CIS_ADDR(cis), len); 3650db7e66cSJonathan Chen return 0; 3660db7e66cSJonathan Chen } 3670db7e66cSJonathan Chen 3680db7e66cSJonathan Chen addr += imagesize; 3690db7e66cSJonathan Chen romnum++; 3700db7e66cSJonathan Chen } while ((READROM(data, 8, CARDBUS_EXROM_DATA_INDICATOR) & 0x80) == 0); 3710db7e66cSJonathan Chen device_printf(dev, "Cannot read CIS: Not enough images of rom\n"); 3720db7e66cSJonathan Chen return ENOENT; 3730db7e66cSJonathan Chen #undef READROM 3740db7e66cSJonathan Chen } 3750db7e66cSJonathan Chen 3760db7e66cSJonathan Chen static int 3770db7e66cSJonathan Chen cardbus_read_tuples_conf(device_t dev, device_t child, u_int32_t cis_ptr, 3780db7e66cSJonathan Chen u_int8_t *tuples, int len) 3790db7e66cSJonathan Chen { 3800db7e66cSJonathan Chen int i, j; 3810db7e66cSJonathan Chen 3820db7e66cSJonathan Chen DEVPRINTF((dev, "reading CIS data from configuration space\n")); 3830db7e66cSJonathan Chen for (i = cis_ptr, j = 0; i < len; i += 4) { 3840db7e66cSJonathan Chen u_int32_t e = pci_read_config(child, i, 4); 3850db7e66cSJonathan Chen tuples[j] = 0xff & e; 3860db7e66cSJonathan Chen e >>= 8; 3870db7e66cSJonathan Chen tuples[j + 1] = 0xff & e; 3880db7e66cSJonathan Chen e >>= 8; 3890db7e66cSJonathan Chen tuples[j + 2] = 0xff & e; 3900db7e66cSJonathan Chen e >>= 8; 3910db7e66cSJonathan Chen tuples[j + 3] = 0xff & e; 3920db7e66cSJonathan Chen j += 4; 3930db7e66cSJonathan Chen } 3940db7e66cSJonathan Chen return 0; 3950db7e66cSJonathan Chen } 3960db7e66cSJonathan Chen 3970db7e66cSJonathan Chen static int 3980db7e66cSJonathan Chen cardbus_read_tuples_mem(device_t dev, device_t child, int space, 3990db7e66cSJonathan Chen u_int32_t cis_ptr, u_int8_t *tuples, int len) 4000db7e66cSJonathan Chen { 4010db7e66cSJonathan Chen struct resource *mem; 4020db7e66cSJonathan Chen int rid; 4030db7e66cSJonathan Chen int ret; 4040db7e66cSJonathan Chen 4050db7e66cSJonathan Chen if(space == CARDBUS_CIS_ASI_ROM) { 4060db7e66cSJonathan Chen rid = CARDBUS_ROM_REG; 4070db7e66cSJonathan Chen DEVPRINTF((dev, "reading CIS data from ROM\n")); 4080db7e66cSJonathan Chen } else { 4090db7e66cSJonathan Chen rid = CARDBUS_BASE0_REG + (space - 1) * 4; 4100db7e66cSJonathan Chen DEVPRINTF((dev, "reading CIS data from BAR%d\n", space - 1)); 4110db7e66cSJonathan Chen } 4120db7e66cSJonathan Chen mem = bus_alloc_resource(child, SYS_RES_MEMORY, &rid, 0, ~0, 4130db7e66cSJonathan Chen 1, RF_ACTIVE); 4140db7e66cSJonathan Chen if (mem == NULL) { 4150db7e66cSJonathan Chen device_printf(dev, "Failed to get memory for CIS reading\n"); 4160db7e66cSJonathan Chen return ENOMEM; 4170db7e66cSJonathan Chen } 4180db7e66cSJonathan Chen 4190db7e66cSJonathan Chen if(space == CARDBUS_CIS_ASI_ROM) { 4200db7e66cSJonathan Chen int s; 4210db7e66cSJonathan Chen s = splhigh(); 4220db7e66cSJonathan Chen ret = cardbus_read_exrom_cis(dev, mem, cis_ptr, tuples, len); 4230db7e66cSJonathan Chen splx(s); 4240db7e66cSJonathan Chen } else { 4250db7e66cSJonathan Chen /* XXX byte order? */ 4260db7e66cSJonathan Chen memcpy(tuples, (unsigned char*)rman_get_virtual(mem)+cis_ptr, 4270db7e66cSJonathan Chen len); 4280db7e66cSJonathan Chen ret = 0; 4290db7e66cSJonathan Chen } 4300db7e66cSJonathan Chen bus_release_resource(child, SYS_RES_MEMORY, rid, mem); 4310db7e66cSJonathan Chen return ret; 4320db7e66cSJonathan Chen } 4330db7e66cSJonathan Chen 4340db7e66cSJonathan Chen static int 4350db7e66cSJonathan Chen cardbus_read_tuples(device_t dev, device_t child, u_int8_t *tuples, int len) 4360db7e66cSJonathan Chen { 4370db7e66cSJonathan Chen u_int32_t cis_ptr = pci_read_config(child, CARDBUS_CIS_REG, 4); 4380db7e66cSJonathan Chen int cardbus_space = cis_ptr & CARDBUS_CIS_ASIMASK; 4390db7e66cSJonathan Chen int ret = 0; 4400db7e66cSJonathan Chen cis_ptr = cis_ptr & CARDBUS_CIS_ADDRMASK; 4410db7e66cSJonathan Chen 4420db7e66cSJonathan Chen switch(cardbus_space) { 4430db7e66cSJonathan Chen case CARDBUS_CIS_ASI_TUPLE: 4440db7e66cSJonathan Chen ret = cardbus_read_tuples_conf(dev, child, cis_ptr, tuples, 4450db7e66cSJonathan Chen len); 4460db7e66cSJonathan Chen break; 4470db7e66cSJonathan Chen case CARDBUS_CIS_ASI_BAR0: 4480db7e66cSJonathan Chen case CARDBUS_CIS_ASI_BAR1: 4490db7e66cSJonathan Chen case CARDBUS_CIS_ASI_BAR2: 4500db7e66cSJonathan Chen case CARDBUS_CIS_ASI_BAR3: 4510db7e66cSJonathan Chen case CARDBUS_CIS_ASI_BAR4: 4520db7e66cSJonathan Chen case CARDBUS_CIS_ASI_BAR5: 4530db7e66cSJonathan Chen case CARDBUS_CIS_ASI_ROM: 4540db7e66cSJonathan Chen ret = cardbus_read_tuples_mem(dev, child, cardbus_space, 4550db7e66cSJonathan Chen cis_ptr, tuples, len); 4560db7e66cSJonathan Chen break; 4570db7e66cSJonathan Chen default: 4580db7e66cSJonathan Chen device_printf(dev, "Unable to read CIS: Unknown space: %d\n", 4590db7e66cSJonathan Chen cardbus_space); 4600db7e66cSJonathan Chen ret = EINVAL; 4610db7e66cSJonathan Chen } 4620db7e66cSJonathan Chen return ret; 4630db7e66cSJonathan Chen } 4640db7e66cSJonathan Chen 4650db7e66cSJonathan Chen int 4660db7e66cSJonathan Chen cardbus_do_cis(device_t dev, device_t child) 4670db7e66cSJonathan Chen { 4680db7e66cSJonathan Chen u_int8_t tupledata[MAXTUPLESIZE]; 4690db7e66cSJonathan Chen int ret; 4700db7e66cSJonathan Chen 4710db7e66cSJonathan Chen bzero(tupledata, MAXTUPLESIZE); 4720db7e66cSJonathan Chen 4730db7e66cSJonathan Chen ret = cardbus_read_tuples(dev, child, tupledata, MAXTUPLESIZE); 4740db7e66cSJonathan Chen if (ret != 0) return ret; 4750db7e66cSJonathan Chen return decode_tuples(dev, child, tupledata, MAXTUPLESIZE); 4760db7e66cSJonathan Chen } 4770db7e66cSJonathan Chen 478