Annotation of sys/dev/pci/if_sandrv.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: if_sandrv.c,v 1.11 2006/04/20 20:31:12 miod Exp $ */
! 2:
! 3: /*-
! 4: * Copyright (c) 2001-2004 Sangoma Technologies (SAN)
! 5: * All rights reserved. www.sangoma.com
! 6: *
! 7: * This code is written by Alex Feldman <al.feldman@sangoma.com> for SAN.
! 8: *
! 9: * Redistribution and use in source and binary forms, with or without
! 10: * modification, are permitted provided that the following conditions
! 11: * are met:
! 12: * 1. Redistributions of source code must retain the above copyright
! 13: * notice, this list of conditions and the following disclaimer.
! 14: * 2. Redistributions in binary form must reproduce the above
! 15: * copyright notice, this list of conditions and the following disclaimer
! 16: * in the documentation and/or other materials provided with the
! 17: * distribution.
! 18: * 3. Neither the name of Sangoma Technologies nor the names of its
! 19: * contributors may be used to endorse or promote products derived
! 20: * from this software without specific prior written permission.
! 21: *
! 22: * THIS SOFTWARE IS PROVIDED BY SANGOMA TECHNOLOGIES AND CONTRIBUTORS
! 23: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 24: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 25: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
! 26: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 27: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 28: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 29: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 30: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 31: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
! 32: * THE POSSIBILITY OF SUCH DAMAGE.
! 33: */
! 34:
! 35: #define __SDLA_HW_LEVEL
! 36: #define __SDLADRV__
! 37:
! 38: #include <sys/types.h>
! 39: #include <sys/param.h>
! 40: #include <sys/systm.h>
! 41: #include <sys/syslog.h>
! 42: #include <sys/malloc.h>
! 43: #include <sys/kernel.h>
! 44:
! 45: #include <dev/pci/pcireg.h>
! 46: #include <dev/pci/pcivar.h>
! 47: #include <dev/pci/if_san_front_end.h>
! 48: #include <dev/pci/if_sandrv.h>
! 49:
! 50: #define EXEC_DELAY 20 /* shared memory access delay, mks */
! 51: #define EXEC_TIMEOUT (hz*2)
! 52: #define MAX_NLOOPS (EXEC_DELAY*2000)
! 53: /* timeout used if jiffies are stopped
! 54: ** EXEC_DELAY=20
! 55: ** EXEC_TIMEOUT=EXEC_DELAY*2000 = 40000
! 56: ** 40000 ~= 80 jiffies = EXEC_TIMEOUT */
! 57:
! 58: #define EXEC_HZ_DIVISOR 8/10
! 59: /* We don't want to wait a full second on sdla_exec
! 60: ** timeout, thus use HZ * EXEC_HZ_DIVISOR to get
! 61: ** the number of jiffies we would like to wait */
! 62:
! 63: #define IS_SUPPORTED_ADAPTER(hw) ((hw)->type == SDLA_AFT)
! 64:
! 65: #define SDLA_CTYPE_NAME(type) \
! 66: ((type) == SDLA_AFT) ? "AFT" : "Unknown"
! 67:
! 68: #define IS_AFT(hw) (hw->type == SDLA_AFT)
! 69:
! 70: /* Definitions for identifying and finding S514 PCI adapters */
! 71: #define V3_VENDOR_ID 0x11B0 /* V3 vendor ID number */
! 72: #define V3_DEVICE_ID 0x0002 /* V3 device ID number */
! 73: #define SANGOMA_SUBSYS_VENDOR 0x4753 /* ID for Sangoma */
! 74:
! 75: /* Definition for identifying and finding XILINX PCI adapters */
! 76: #define SANGOMA_PCI_VENDOR 0x1923 /* Old value -> 0x11B0 */
! 77: #define SANGOMA_PCI_VENDOR_OLD 0x10EE /* Old value -> 0x11B0 */
! 78: #define SANGOMA_PCI_DEVICE 0x0300 /* Old value -> 0x0200 */
! 79:
! 80: #define A101_1TE1_SUBSYS_VENDOR 0xA010 /* A101 with T1/E1 1 line */
! 81: #define A101_2TE1_SUBSYS_VENDOR 0xA011 /* A101 with T1/E1 2 lines */
! 82: #define A105_T3_SUBSYS_VENDOR 0xA020 /* A102 with T3 */
! 83:
! 84: /* Read PCI SUBVENDOR ID */
! 85: #define PCI_SUBVENDOR_MASK 0xFFFF
! 86: #define PCI_SUBVENDOR(pa) (pci_conf_read(pa->pa_pc, pa->pa_tag, \
! 87: PCI_SUBSYS_ID_REG) & PCI_SUBVENDOR_MASK)
! 88: #define PCI_DEVICE_MASK 0xFFFF0000
! 89: #define PCI_DEVICE(id) ((id & PCI_DEVICE_MASK ) >> 16)
! 90:
! 91: /* Status values */
! 92: #define SDLA_MEM_RESERVED 0x0001
! 93: #define SDLA_MEM_MAPPED 0x0002
! 94: #define SDLA_IO_MAPPED 0x0004
! 95: #define SDLA_PCI_ENABLE 0x0008
! 96:
! 97: struct san_softc {
! 98: struct device dev;
! 99: struct pci_attach_args pa;
! 100: };
! 101:
! 102: typedef struct sdla_hw_probe {
! 103: int used;
! 104: unsigned char hw_info[100];
! 105: LIST_ENTRY(sdla_hw_probe) next;
! 106: } sdla_hw_probe_t;
! 107:
! 108: /*
! 109: * This structure keeps common parameters per physical card.
! 110: */
! 111: typedef struct sdlahw_card {
! 112: int used;
! 113: unsigned int type; /* S50x/S514/ADSL/XILINX */
! 114: unsigned int atype; /* SubVendor ID */
! 115: unsigned char core_id; /* SubSystem ID [0..7] */
! 116: unsigned char core_rev; /* SubSystem ID [8..15] */
! 117: unsigned char pci_extra_ver;
! 118: unsigned int slot_no;
! 119: unsigned int bus_no;
! 120: bus_space_tag_t memt;
! 121: struct pci_attach_args pa; /* PCI config header info */
! 122: pci_intr_handle_t ih;
! 123: LIST_ENTRY(sdlahw_card) next;
! 124: } sdlahw_card_t;
! 125:
! 126: /*
! 127: * Adapter hardware configuration. Pointer to this structure is passed to all
! 128: * APIs.
! 129: */
! 130: typedef struct sdlahw {
! 131: int used;
! 132: unsigned magic;
! 133: char devname[20];
! 134: u_int16_t status;
! 135: int irq; /* interrupt request level */
! 136: unsigned int cpu_no; /* PCI CPU Number */
! 137: char auto_pci_cfg; /* Auto PCI configuration */
! 138: bus_addr_t mem_base_addr;
! 139: bus_space_handle_t dpmbase; /* dual-port memory base */
! 140: unsigned dpmsize; /* dual-port memory size */
! 141: unsigned long memory; /* memory size */
! 142:
! 143: unsigned reserved[5];
! 144: unsigned char hw_info[100];
! 145:
! 146: u_int16_t configured;
! 147: void *arg; /* card structure */
! 148: sdla_hw_probe_t *hwprobe;
! 149: sdlahw_card_t *hwcard;
! 150: LIST_ENTRY(sdlahw) next;
! 151: } sdlahw_t;
! 152:
! 153: /* Entry Point for Low-Level function */
! 154: int sdladrv_init(void);
! 155: int sdladrv_exit(void);
! 156:
! 157: static int sdla_pci_probe(int, struct pci_attach_args *);
! 158:
! 159: /* PCI bus interface function */
! 160: static int sdla_pci_write_config_word(void *, int, u_int16_t);
! 161: static int sdla_pci_write_config_dword(void *, int, u_int32_t);
! 162: static int sdla_pci_read_config_byte(void *, int, u_int8_t *);
! 163: static int sdla_pci_read_config_word(void *, int, u_int16_t *);
! 164: static int sdla_pci_read_config_dword(void *, int, u_int32_t *);
! 165:
! 166: static int sdla_detect (sdlahw_t *);
! 167: static int sdla_detect_aft(sdlahw_t *);
! 168: static int sdla_exec(sdlahw_t *, unsigned long);
! 169: static void sdla_peek_by_4(sdlahw_t *, unsigned long, void *, unsigned int);
! 170: static void sdla_poke_by_4(sdlahw_t *, unsigned long, void *, unsigned int);
! 171:
! 172: static sdlahw_card_t* sdla_card_register(u_int16_t, int, int);
! 173: #if 0
! 174: static int sdla_card_unregister (unsigned char, int, int, int);
! 175: #endif
! 176: static sdlahw_card_t* sdla_card_search(u_int16_t, int, int);
! 177:
! 178: static sdlahw_t* sdla_hw_register(sdlahw_card_t *, int, int, void *);
! 179: #if 0
! 180: static int sdla_hw_unregister(sdlahw_card_t*, int);
! 181: #endif
! 182: static sdlahw_t* sdla_hw_search(u_int16_t, int, int, int);
! 183:
! 184: static sdlahw_t* sdla_aft_hw_select (sdlahw_card_t *, int, int,
! 185: struct pci_attach_args *);
! 186: static void sdla_save_hw_probe (sdlahw_t*, int);
! 187:
! 188: /* SDLA PCI device relative entry point */
! 189: int san_match(struct device *, void *, void *);
! 190: void san_attach(struct device *, struct device *, void *);
! 191:
! 192:
! 193: struct cfdriver san_cd = {
! 194: NULL, "san", DV_IFNET
! 195: };
! 196:
! 197: struct cfattach san_ca = {
! 198: sizeof(struct san_softc), san_match, san_attach
! 199: };
! 200:
! 201: extern int ticks;
! 202:
! 203: /* SDLA ISA/PCI varibles */
! 204: static int Sangoma_cards_no = 0;
! 205: static int Sangoma_devices_no = 0;
! 206: static int Sangoma_PCI_cards_no = 0;
! 207:
! 208: /* private data */
! 209: char *san_drvname = "san";
! 210:
! 211: /* Array of already initialized PCI slots */
! 212: static int pci_slot_ar[MAX_S514_CARDS];
! 213:
! 214: LIST_HEAD(, sdlahw_card) sdlahw_card_head =
! 215: LIST_HEAD_INITIALIZER(sdlahw_card_head);
! 216: LIST_HEAD(, sdlahw) sdlahw_head =
! 217: LIST_HEAD_INITIALIZER(sdlahw_head);
! 218: LIST_HEAD(, sdla_hw_probe) sdlahw_probe_head =
! 219: LIST_HEAD_INITIALIZER(sdlahw_probe_head);
! 220: static sdla_hw_type_cnt_t sdla_adapter_cnt;
! 221:
! 222:
! 223:
! 224: /*
! 225: * PCI Device Driver Entry Points
! 226: */
! 227: int
! 228: san_match(struct device *parent, void *match, void *aux)
! 229: {
! 230: struct pci_attach_args* pa = aux;
! 231: u_int16_t vendor_id = PCI_VENDOR(pa->pa_id);
! 232: u_int16_t device_id = PCI_DEVICE(pa->pa_id);
! 233:
! 234: if ((vendor_id == SANGOMA_PCI_VENDOR ||
! 235: vendor_id == SANGOMA_PCI_VENDOR_OLD) &&
! 236: device_id == SANGOMA_PCI_DEVICE) {
! 237: return (1);
! 238: }
! 239: return (0);
! 240: }
! 241:
! 242: #define PCI_CBIO 0x10
! 243: void
! 244: san_attach(struct device *parent, struct device *self, void *aux)
! 245: {
! 246: struct pci_attach_args* pa = aux;
! 247: u_int16_t vendor_id = PCI_VENDOR(pa->pa_id);
! 248: u_int16_t subvendor_id = PCI_SUBVENDOR(pa);
! 249: int atype = 0x00;
! 250:
! 251: atype = PCI_PRODUCT(pci_conf_read(pa->pa_pc, pa->pa_tag,
! 252: PCI_SUBSYS_ID_REG));
! 253: switch (vendor_id) {
! 254: case SANGOMA_PCI_VENDOR_OLD:
! 255: case SANGOMA_PCI_VENDOR:
! 256: switch (subvendor_id) {
! 257: case A101_1TE1_SUBSYS_VENDOR:
! 258: atype = A101_ADPTR_1TE1;
! 259: break;
! 260: case A101_2TE1_SUBSYS_VENDOR:
! 261: atype = A101_ADPTR_2TE1;
! 262: break;
! 263: default:
! 264: return;
! 265: }
! 266: break;
! 267: default:
! 268: return;
! 269: }
! 270:
! 271: if (sdla_pci_probe(atype, pa)) {
! 272: printf(": PCI probe FAILED!\n");
! 273: return;
! 274: }
! 275:
! 276: #ifdef DEBUG
! 277: switch (PCI_VENDOR(pa->pa_id)) {
! 278: case V3_VENDOR_ID:
! 279: switch (atype) {
! 280: case S5141_ADPTR_1_CPU_SERIAL:
! 281: log(LOG_INFO, "%s: Sangoma S5141/FT1 (Single CPU) "
! 282: "adapter\n", self->dv_xname);
! 283: break;
! 284: case S5142_ADPTR_2_CPU_SERIAL:
! 285: log(LOG_INFO, "%s: Sangoma S5142 (Dual CPU) adapter\n",
! 286: self->dv_xname);
! 287: break;
! 288: case S5143_ADPTR_1_CPU_FT1:
! 289: log(LOG_INFO, "%s: Sangoma S5143 (Single CPU) "
! 290: "FT1 adapter\n", self->dv_xname);
! 291: break;
! 292: case S5144_ADPTR_1_CPU_T1E1:
! 293: case S5148_ADPTR_1_CPU_T1E1:
! 294: log(LOG_INFO, "%s: Sangoma S5144 (Single CPU) "
! 295: "T1/E1 adapter\n", self->dv_xname);
! 296: break;
! 297: case S5145_ADPTR_1_CPU_56K:
! 298: log(LOG_INFO, "%s: Sangoma S5145 (Single CPU) "
! 299: "56K adapter\n", self->dv_xname);
! 300: break;
! 301: case S5147_ADPTR_2_CPU_T1E1:
! 302: log(LOG_INFO, "%s: Sangoma S5147 (Dual CPU) "
! 303: "T1/E1 adapter\n", self->dv_xname);
! 304: break;
! 305: }
! 306: break;
! 307:
! 308: case SANGOMA_PCI_VENDOR_OLD:
! 309: switch (atype) {
! 310: case A101_ADPTR_1TE1:
! 311: log(LOG_INFO, "%s: Sangoma AFT (1 channel) "
! 312: "T1/E1 adapter\n", self->dv_xname);
! 313: break;
! 314: case A101_ADPTR_2TE1:
! 315: log(LOG_INFO, "%s: Sangoma AFT (2 channels) "
! 316: "T1/E1 adapter\n", self->dv_xname);
! 317: break;
! 318: }
! 319: break;
! 320: }
! 321: #endif
! 322: return;
! 323: }
! 324:
! 325: /*
! 326: * Module init point.
! 327: */
! 328: int
! 329: sdladrv_init(void)
! 330: {
! 331: int volatile i = 0;
! 332:
! 333: /* Initialize the PCI Card array, which
! 334: * will store flags, used to mark
! 335: * card initialization state */
! 336: for (i=0; i<MAX_S514_CARDS; i++)
! 337: pci_slot_ar[i] = 0xFF;
! 338:
! 339: bzero(&sdla_adapter_cnt, sizeof(sdla_hw_type_cnt_t));
! 340:
! 341: return (0);
! 342: }
! 343:
! 344: /*
! 345: * Module deinit point.
! 346: * o release all remaining system resources
! 347: */
! 348: int
! 349: sdladrv_exit(void)
! 350: {
! 351: #if 0
! 352: sdla_hw_probe_t *elm_hw_probe;
! 353: sdlahw_t *elm_hw;
! 354: sdlahw_card_t *elm_hw_card;
! 355:
! 356:
! 357: elm_hw = LIST_FIRST(&sdlahw_head);
! 358: while (elm_hw) {
! 359: sdlahw_t *tmp = elm_hw;
! 360: elm_hw = LIST_NEXT(elm_hw, next);
! 361: if (sdla_hw_unregister(tmp->hwcard, tmp->cpu_no) == EBUSY)
! 362: return EBUSY;
! 363: }
! 364: LIST_INIT(&sdlahw_head);
! 365:
! 366: elm_hw_card = LIST_FIRST(&sdlahw_card_head);
! 367: while (elm_hw_card) {
! 368: sdlahw_card_t *tmp = elm_hw_card;
! 369: elm_hw_card = LIST_NEXT(elm_hw_card, next);
! 370: if (sdla_card_unregister(tmp->hw_type,
! 371: tmp->slot_no,
! 372: tmp->bus_no,
! 373: tmp->ioport) == EBUSY)
! 374: return EBUSY;
! 375: }
! 376: LIST_INIT(&sdlahw_card_head);
! 377:
! 378: elm_hw_probe = LIST_FIRST(&sdlahw_probe_head);
! 379: while (elm_hw_probe) {
! 380: sdla_hw_probe_t *tmp = elm_hw_probe;
! 381: elm_hw_probe = LIST_NEXT(elm_hw_probe, next);
! 382: if (tmp->used){
! 383: log(LOG_INFO, "HW probe info is in used (%s)\n",
! 384: elm_hw_probe->hw_info);
! 385: return EBUSY;
! 386: }
! 387: LIST_REMOVE(tmp, next);
! 388: free(tmp, M_DEVBUF);
! 389: }
! 390: #endif
! 391: return (0);
! 392: }
! 393:
! 394: static void
! 395: sdla_save_hw_probe(sdlahw_t *hw, int port)
! 396: {
! 397: sdla_hw_probe_t *tmp_hw_probe;
! 398:
! 399: tmp_hw_probe = malloc(sizeof(sdla_hw_probe_t), M_DEVBUF, M_NOWAIT);
! 400: if (tmp_hw_probe == NULL)
! 401: return;
! 402:
! 403: bzero(tmp_hw_probe, sizeof(sdla_hw_probe_t));
! 404:
! 405: snprintf(tmp_hw_probe->hw_info, sizeof(tmp_hw_probe->hw_info),
! 406: "%s : SLOT=%d : BUS=%d : IRQ=%d : CPU=%c : PORT=%s",
! 407: SDLA_ADPTR_DECODE(hw->hwcard->atype), hw->hwcard->slot_no,
! 408: hw->hwcard->bus_no, hw->irq, SDLA_GET_CPU(hw->cpu_no), "PRI");
! 409:
! 410: hw->hwprobe = tmp_hw_probe;
! 411: tmp_hw_probe->used++;
! 412: LIST_INSERT_HEAD(&sdlahw_probe_head, tmp_hw_probe, next);
! 413: }
! 414:
! 415: static sdlahw_t*
! 416: sdla_aft_hw_select(sdlahw_card_t *hwcard, int cpu_no,
! 417: int irq, struct pci_attach_args *pa)
! 418: {
! 419: sdlahw_t* hw = NULL;
! 420: int number_of_cards = 0;
! 421:
! 422: hwcard->type = SDLA_AFT;
! 423: switch (hwcard->atype) {
! 424: case A101_ADPTR_1TE1:
! 425: hw = sdla_hw_register(hwcard, cpu_no, irq, pa);
! 426: sdla_save_hw_probe(hw, 0);
! 427: number_of_cards += 1;
! 428: #ifdef DEBUG
! 429: log(LOG_INFO, "%s: %s T1/E1 card found (%s rev.%d), "
! 430: "cpu(s) 1, bus #%d, slot #%d, irq #%d\n", san_drvname,
! 431: SDLA_ADPTR_DECODE(hwcard->atype),
! 432: AFT_CORE_ID_DECODE(hwcard->core_id), hwcard->core_rev,
! 433: hwcard->bus_no, hwcard->slot_no, irq);
! 434: #endif /* DEBUG */
! 435: break;
! 436: case A101_ADPTR_2TE1:
! 437: hw = sdla_hw_register(hwcard, cpu_no, irq, pa);
! 438: sdla_save_hw_probe(hw, 0);
! 439: number_of_cards += 1;
! 440: #ifdef DEBUG
! 441: log(LOG_INFO, "%s: %s T1/E1 card found (%s rev.%d), "
! 442: "cpu(s) 2, bus #%d, slot #%d, irq #%d\n", san_drvname,
! 443: SDLA_ADPTR_DECODE(hwcard->atype),
! 444: AFT_CORE_ID_DECODE(hwcard->core_id), hwcard->core_rev,
! 445: hwcard->bus_no, hwcard->slot_no, irq);
! 446: #endif /* DEBUG */
! 447: break;
! 448: case A105_ADPTR_1_CHN_T3E3:
! 449:
! 450: hw = sdla_hw_register(hwcard, cpu_no, irq, pa);
! 451: sdla_save_hw_probe(hw, 0);
! 452: number_of_cards += 1;
! 453: #ifdef DEBUG
! 454: log(LOG_INFO, "%s: %s T3/E3 card found, cpu(s) 1,"
! 455: "bus #%d, slot #%d, irq #%d\n", san_drvname,
! 456: SDLA_ADPTR_DECODE(hwcard->atype),
! 457: hwcard->bus_no, hwcard->slot_no, irq);
! 458: #endif /* DEBUG */
! 459: break;
! 460: default:
! 461: log(LOG_INFO, "%s: Unknown adapter %04X "
! 462: "(bus #%d, slot #%d, irq #%d)!\n", san_drvname,
! 463: hwcard->atype, hwcard->bus_no, hwcard->slot_no, irq);
! 464: break;
! 465: }
! 466:
! 467: return (hw);
! 468: }
! 469:
! 470:
! 471: static int
! 472: sdla_pci_probe(int atype, struct pci_attach_args *pa)
! 473: {
! 474: sdlahw_card_t* hwcard;
! 475: sdlahw_t* hw;
! 476: /*sdladev_t* dev = NULL;*/
! 477: int dual_cpu = 0;
! 478: int bus, slot, cpu = SDLA_CPU_A;
! 479: u_int16_t vendor_id, subvendor_id, device_id;
! 480: u_int8_t irq;
! 481: pci_intr_handle_t ih;
! 482: const char* intrstr = NULL;
! 483:
! 484: bus = pa->pa_bus;
! 485: slot = pa->pa_device;
! 486: vendor_id = PCI_VENDOR(pa->pa_id);
! 487: subvendor_id = PCI_SUBVENDOR(pa);
! 488: device_id = PCI_DEVICE(pa->pa_id);
! 489: irq = (u_int8_t)pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_INTLINE);
! 490:
! 491: /* Map and establish the interrupt */
! 492: if (pci_intr_map(pa, &ih)) {
! 493: printf(": couldn't map interrupt\n");
! 494: return (EINVAL);
! 495: }
! 496: intrstr = pci_intr_string(pa->pa_pc, ih);
! 497: if (intrstr != NULL)
! 498: printf(" %s\n", intrstr);
! 499:
! 500: Sangoma_cards_no ++;
! 501: reg_new_card:
! 502: Sangoma_PCI_cards_no ++;
! 503: hwcard = sdla_card_register(atype, slot, bus);
! 504: if (hwcard == NULL)
! 505: return (EINVAL);
! 506:
! 507: hwcard->memt = pa->pa_memt;
! 508: hwcard->ih = ih;
! 509: hwcard->pa = *pa;
! 510: /* Increment number of available Sangoma devices */
! 511: Sangoma_devices_no ++;
! 512: switch (atype) {
! 513: case A101_ADPTR_1TE1:
! 514: case A101_ADPTR_2TE1:
! 515: hw = sdla_aft_hw_select(hwcard, cpu, irq, pa);
! 516: sdla_adapter_cnt.AFT_adapters++;
! 517: if (atype == A101_ADPTR_2TE1)
! 518: dual_cpu = 1;
! 519: break;
! 520:
! 521: }
! 522:
! 523: if (hw == NULL)
! 524: return (EINVAL);
! 525: if (san_dev_attach(hw, hw->devname, sizeof(hw->devname)))
! 526: return (EINVAL);
! 527:
! 528: hw->used++;
! 529:
! 530: if (dual_cpu && cpu == SDLA_CPU_A) {
! 531: cpu = SDLA_CPU_B;
! 532: goto reg_new_card;
! 533: }
! 534:
! 535: return (0);
! 536: }
! 537:
! 538: int
! 539: sdla_intr_establish(void *phw, int (*intr_func)(void*), void* intr_arg)
! 540: {
! 541: sdlahw_t *hw = (sdlahw_t*)phw;
! 542: sdlahw_card_t *hwcard;
! 543:
! 544: WAN_ASSERT(hw == NULL);
! 545: hwcard = hw->hwcard;
! 546: if (pci_intr_establish(hwcard->pa.pa_pc, hwcard->ih, IPL_NET,
! 547: intr_func, intr_arg, "san") == NULL)
! 548: return (EINVAL);
! 549:
! 550: return 0;
! 551: }
! 552:
! 553: int
! 554: sdla_intr_disestablish(void *phw)
! 555: {
! 556: sdlahw_t *hw = (sdlahw_t*)phw;
! 557:
! 558: log(LOG_INFO, "%s: Disestablish interrupt is not defined!\n",
! 559: hw->devname);
! 560: return (EINVAL);
! 561: }
! 562:
! 563: int
! 564: sdla_get_hw_devices(void)
! 565: {
! 566: return (Sangoma_devices_no);
! 567: }
! 568:
! 569: void*
! 570: sdla_get_hw_adptr_cnt(void)
! 571: {
! 572: return (&sdla_adapter_cnt);
! 573: }
! 574:
! 575: static sdlahw_card_t*
! 576: sdla_card_register(u_int16_t atype, int slot_no, int bus_no)
! 577: {
! 578: sdlahw_card_t *new_hwcard, *last_hwcard;
! 579:
! 580: new_hwcard = sdla_card_search(atype, slot_no, bus_no);
! 581: if (new_hwcard)
! 582: return (new_hwcard);
! 583:
! 584: new_hwcard = malloc(sizeof(sdlahw_card_t), M_DEVBUF, M_NOWAIT);
! 585: if (!new_hwcard)
! 586: return (NULL);
! 587:
! 588: bzero(new_hwcard, sizeof(sdlahw_card_t));
! 589:
! 590: new_hwcard->atype = atype;
! 591: new_hwcard->slot_no = slot_no;
! 592: new_hwcard->bus_no = bus_no;
! 593:
! 594: if (LIST_EMPTY(&sdlahw_card_head)) {
! 595: /* Initialize SAN HW parameters */
! 596: sdladrv_init();
! 597: }
! 598: LIST_FOREACH(last_hwcard, &sdlahw_card_head, next) {
! 599: if (!LIST_NEXT(last_hwcard, next))
! 600: break;
! 601: }
! 602:
! 603: if (last_hwcard)
! 604: LIST_INSERT_AFTER(last_hwcard, new_hwcard, next);
! 605: else
! 606: LIST_INSERT_HEAD(&sdlahw_card_head, new_hwcard, next);
! 607:
! 608: return (new_hwcard);
! 609: }
! 610:
! 611: #if 0
! 612: static int
! 613: sdla_card_unregister(u_int16_t atype, int slot_no, int bus_no, int ioport)
! 614: {
! 615: sdlahw_card_t* tmp_card;
! 616:
! 617: LIST_FOREACH(tmp_card, &sdlahw_card_head, next){
! 618: if (tmp_card->atype != atype){
! 619: continue;
! 620: }
! 621: if (tmp_card->slot_no == slot_no &&
! 622: tmp_card->bus_no == bus_no){
! 623: break;
! 624: }
! 625: }
! 626: if (tmp_card == NULL){
! 627: log(LOG_INFO,
! 628: "Error: Card didn't find %04X card (slot=%d, bus=%d)\n"
! 629: atype, slot_no, bus_no);
! 630: return (EFAULT)
! 631: }
! 632: if (tmp_card->used){
! 633: log(LOG_INFO,
! 634: "Error: Card is still in used (slot=%d,bus=%d,used=%d)\n",
! 635: slot_no, bus_no, tmp_card->used);
! 636: return (EBUSY);
! 637: }
! 638: LIST_REMOVE(tmp_card, next);
! 639: free(tmp_card, M_DEVBUF);
! 640: return 0;
! 641: }
! 642: #endif
! 643:
! 644: static sdlahw_card_t*
! 645: sdla_card_search(u_int16_t atype, int slot_no, int bus_no)
! 646: {
! 647: sdlahw_card_t* tmp_card;
! 648:
! 649: LIST_FOREACH(tmp_card, &sdlahw_card_head, next) {
! 650: if (tmp_card->atype != atype)
! 651: continue;
! 652:
! 653: if (tmp_card->slot_no == slot_no &&
! 654: tmp_card->bus_no == bus_no)
! 655: return (tmp_card);
! 656: }
! 657: return (NULL);
! 658: }
! 659:
! 660: static sdlahw_t*
! 661: sdla_hw_register(sdlahw_card_t *card, int cpu_no, int irq, void *dev)
! 662: {
! 663: sdlahw_t *new_hw, *last_hw;
! 664:
! 665: new_hw = sdla_hw_search(card->atype, card->slot_no,
! 666: card->bus_no, cpu_no);
! 667: if (new_hw)
! 668: return (new_hw);
! 669:
! 670: new_hw = malloc(sizeof(sdlahw_t), M_DEVBUF, M_NOWAIT);
! 671: if (!new_hw)
! 672: return (NULL);
! 673:
! 674: bzero(new_hw, sizeof(sdlahw_t));
! 675:
! 676: new_hw->cpu_no = cpu_no;
! 677: new_hw->irq = irq;
! 678: new_hw->hwcard = card;
! 679: #if 0
! 680: new_hw->dev = dev;
! 681: #endif
! 682: new_hw->magic = SDLAHW_MAGIC;
! 683: card->used++;
! 684:
! 685: LIST_FOREACH(last_hw, &sdlahw_head, next) {
! 686: if (!LIST_NEXT(last_hw, next))
! 687: break;
! 688: }
! 689: if (last_hw)
! 690: LIST_INSERT_AFTER(last_hw, new_hw, next);
! 691: else
! 692: LIST_INSERT_HEAD(&sdlahw_head, new_hw, next);
! 693:
! 694: return (new_hw);
! 695: }
! 696:
! 697: #if 0
! 698: static int
! 699: sdla_hw_unregister(sdlahw_card_t* hwcard, int cpu_no)
! 700: {
! 701: sdlahw_t* tmp_hw;
! 702: int i;
! 703:
! 704: LIST_FOREACH(tmp_hw, &sdlahw_head, next) {
! 705: if (tmp_hw->hwcard != hwcard)
! 706: continue;
! 707:
! 708: if (tmp_hw->cpu_no == cpu_no)
! 709: break;
! 710: }
! 711:
! 712: if (tmp_hw == NULL) {
! 713: log(LOG_INFO,
! 714: "Error: Failed to find device (slot=%d,bus=%d,cpu=%c)\n",
! 715: hwcard->slot_no, hwcard->bus_no, SDLA_GET_CPU(cpu_no));
! 716: return (EFAULT);
! 717: }
! 718: if (tmp_hw->used) {
! 719: log(LOG_INFO,
! 720: "Error: Device is still in used (slot=%d,bus=%d,cpu=%c,%d)\n",
! 721: hwcard->slot_no,
! 722: hwcard->bus_no,
! 723: SDLA_GET_CPU(cpu_no),
! 724: hwcard->used);
! 725: return (EBUSY);
! 726: }
! 727:
! 728: tmp_hw->hwprobe = NULL;
! 729: tmp_hw->hwcard = NULL;
! 730: hwcard->used--; /* Decrement card usage */
! 731: LIST_REMOVE(tmp_hw, next);
! 732: free(tmp_hw, M_DEVBUF);
! 733:
! 734: return (0);
! 735: }
! 736: #endif
! 737:
! 738: static sdlahw_t*
! 739: sdla_hw_search(u_int16_t atype, int slot_no, int bus_no, int cpu_no)
! 740: {
! 741: sdlahw_t* tmp_hw;
! 742:
! 743:
! 744: LIST_FOREACH(tmp_hw, &sdlahw_head, next) {
! 745: if (tmp_hw->hwcard == NULL) {
! 746: log(LOG_INFO,
! 747: "Critical Error: sdla_cpu_search: line %d\n",
! 748: __LINE__);
! 749: // XXX REMOVE in LIST_FOREACH
! 750: LIST_REMOVE(tmp_hw, next);
! 751: continue;
! 752: }
! 753: if (tmp_hw->hwcard->atype != atype) {
! 754: // XXX why ???
! 755: LIST_REMOVE(tmp_hw, next);
! 756: continue;
! 757: }
! 758: if (tmp_hw->hwcard->slot_no == slot_no &&
! 759: tmp_hw->hwcard->bus_no == bus_no &&
! 760: tmp_hw->cpu_no == cpu_no)
! 761: return (tmp_hw);
! 762: }
! 763:
! 764: return (NULL);
! 765: }
! 766:
! 767:
! 768: /*
! 769: * Set up adapter.
! 770: * o detect adapter type
! 771: * o set up adapter shared memory
! 772: * Return: 0 ok.
! 773: * < 0 error
! 774: */
! 775:
! 776: int
! 777: sdla_setup(void *phw)
! 778: {
! 779: sdlahw_card_t* hwcard = NULL;
! 780: sdlahw_t* hw = (sdlahw_t*)phw;
! 781: int err=0;
! 782:
! 783: WAN_ASSERT(hw == NULL);
! 784: SDLA_MAGIC(hw);
! 785: WAN_ASSERT(hw->hwcard == NULL);
! 786: hwcard = hw->hwcard;
! 787: switch (hwcard->type) {
! 788: case SDLA_AFT:
! 789: break;
! 790:
! 791: default:
! 792: log(LOG_INFO, "%s: Invalid card type %x\n",
! 793: hw->devname, hw->hwcard->type);
! 794: return (EINVAL);
! 795: }
! 796:
! 797: hw->dpmsize = SDLA_WINDOWSIZE;
! 798:
! 799: err = sdla_detect(hw);
! 800: return (err);
! 801: }
! 802:
! 803:
! 804: /*
! 805: * Shut down SDLA: disable shared memory access and interrupts, stop CPU, etc.
! 806: */
! 807: int
! 808: sdla_down(void *phw)
! 809: {
! 810: sdlahw_card_t* card = NULL;
! 811: sdlahw_t* hw = (sdlahw_t*)phw;
! 812:
! 813: WAN_ASSERT(hw == NULL);
! 814: SDLA_MAGIC(hw);
! 815: WAN_ASSERT(hw->hwcard == NULL);
! 816: card = hw->hwcard;
! 817: switch (card->type) {
! 818: case SDLA_AFT:
! 819: /* free up the allocated virtual memory */
! 820: if (hw->status & SDLA_MEM_MAPPED) {
! 821: bus_space_unmap(hw->hwcard->memt,
! 822: hw->dpmbase,
! 823: XILINX_PCI_MEM_SIZE);
! 824: hw->status &= ~SDLA_MEM_MAPPED;
! 825: }
! 826: break;
! 827:
! 828: default:
! 829: return (EINVAL);
! 830: }
! 831: return (0);
! 832: }
! 833:
! 834: /*
! 835: * Read the hardware interrupt status.
! 836: */
! 837: int
! 838: sdla_read_int_stat(void *phw, u_int32_t *int_status)
! 839: {
! 840: sdlahw_card_t* card = NULL;
! 841: sdlahw_t* hw = (sdlahw_t*)phw;
! 842:
! 843: WAN_ASSERT(hw == NULL);
! 844: SDLA_MAGIC(hw);
! 845: WAN_ASSERT(hw->hwcard == NULL);
! 846: card = hw->hwcard;
! 847: switch (card->type) {
! 848: case SDLA_AFT:
! 849: sdla_pci_read_config_dword(hw, PCI_INT_STATUS, int_status);
! 850: }
! 851: return (0);
! 852: }
! 853:
! 854:
! 855: /*
! 856: * Generate an interrupt to adapter's CPU.
! 857: */
! 858: int
! 859: sdla_cmd(void *phw, unsigned long offset, wan_mbox_t *mbox)
! 860: {
! 861: sdlahw_t *hw = (sdlahw_t*)phw;
! 862: int len = sizeof(wan_cmd_t);
! 863: int err = 0;
! 864: u_int8_t value;
! 865:
! 866: SDLA_MAGIC(hw);
! 867: len += mbox->wan_data_len;
! 868:
! 869: sdla_peek(hw, offset, (void*)&value, 1);
! 870: if (value != 0x00) {
! 871: log(LOG_INFO, "%s: opp flag set on entry to sdla_exec!\n",
! 872: hw->devname);
! 873: return (0);
! 874: }
! 875: mbox->wan_opp_flag = 0x00;
! 876: sdla_poke(hw, offset, (void*)mbox, len);
! 877:
! 878: err = sdla_exec(hw, offset);
! 879: if (!err) {
! 880: log(LOG_INFO, "%s: Command 0x%02X failed!\n",
! 881: hw->devname, mbox->wan_command);
! 882: return (WAN_CMD_TIMEOUT);
! 883: }
! 884: sdla_peek(hw, offset, (void*)mbox, sizeof(wan_cmd_t));
! 885: if (mbox->wan_data_len) {
! 886: sdla_peek(hw, offset+offsetof(wan_mbox_t, wan_data),
! 887: mbox->wan_data, mbox->wan_data_len);
! 888: }
! 889:
! 890: return (mbox->wan_return_code);
! 891: }
! 892:
! 893: /*
! 894: * Execute Adapter Command.
! 895: * o Set exec flag.
! 896: * o Busy-wait until flag is reset.
! 897: * o Return number of loops made, or 0 if command timed out.
! 898: */
! 899: static int
! 900: sdla_exec(sdlahw_t *hw, unsigned long offset)
! 901: {
! 902: volatile unsigned long tstop;
! 903: volatile unsigned long nloops;
! 904: u_int8_t value;
! 905:
! 906: value = 0x01;
! 907: sdla_poke(hw, offset, (void*)&value, 1);
! 908: tstop = ticks + EXEC_TIMEOUT;
! 909:
! 910: sdla_peek(hw, offset, (void*)&value, 1);
! 911: for (nloops = 1; value == 0x01; ++ nloops) {
! 912: DELAY(EXEC_DELAY);
! 913: if (ticks > tstop || nloops > MAX_NLOOPS) {
! 914: log(LOG_INFO, "%s: Timeout %lu ticks (max=%lu) "
! 915: "loops %lu (max=%u)\n", hw->devname,
! 916: (ticks-tstop+EXEC_TIMEOUT),
! 917: (unsigned long)EXEC_TIMEOUT, nloops, MAX_NLOOPS);
! 918: return (0); /* time is up! */
! 919: }
! 920: sdla_peek(hw, offset, (void*)&value, 1);
! 921: }
! 922:
! 923: return (nloops);
! 924: }
! 925:
! 926:
! 927: /*
! 928: * Read absolute adapter memory.
! 929: * Transfer data from adapter's memory to data buffer.
! 930: *
! 931: * Note:
! 932: * Care should be taken when crossing dual-port memory window boundary.
! 933: * This function is not atomic, so caller must disable interrupt if
! 934: * interrupt routines are accessing adapter shared memory.
! 935: */
! 936: int
! 937: sdla_peek(void *phw, unsigned long addr, void *buf, unsigned len)
! 938: {
! 939: sdlahw_card_t* card = NULL;
! 940: sdlahw_t* hw = (sdlahw_t*)phw;
! 941: int err = 0;
! 942:
! 943: WAN_ASSERT(hw == NULL);
! 944: SDLA_MAGIC(hw);
! 945: WAN_ASSERT(hw->hwcard == NULL);
! 946: card = hw->hwcard;
! 947: if (addr + len > hw->memory) /* verify arguments */
! 948: return (EINVAL);
! 949:
! 950: switch (card->type) {
! 951: case SDLA_AFT:
! 952: sdla_peek_by_4(hw, addr, buf, len);
! 953: break;
! 954:
! 955: default:
! 956: log(LOG_INFO, "%s: Invalid card type 0x%X\n",
! 957: __FUNCTION__,card->type);
! 958: err = (EINVAL);
! 959: break;
! 960: }
! 961: return (err);
! 962: }
! 963:
! 964:
! 965: /*
! 966: * Read data from adapter's memory to a data buffer in 4-byte chunks.
! 967: * Note that we ensure that the SDLA memory address is on a 4-byte boundary
! 968: * before we begin moving the data in 4-byte chunks.
! 969: */
! 970: static void
! 971: sdla_peek_by_4(sdlahw_t *hw, unsigned long offset, void *buf, unsigned int len)
! 972: {
! 973: /* byte copy data until we get to a 4-byte boundary */
! 974: while (len && (offset & 0x03)) {
! 975: sdla_bus_read_1(hw, offset++, (u_int8_t*)buf);
! 976: ((u_int8_t *)buf)++;
! 977: len--;
! 978: }
! 979:
! 980: /* copy data in 4-byte chunks */
! 981: while (len >= 4) {
! 982: sdla_bus_read_4(hw, offset, (u_int32_t*)buf);
! 983: (u_int8_t*)buf += 4;
! 984: offset += 4;
! 985: len -= 4;
! 986: }
! 987:
! 988: /* byte copy any remaining data */
! 989: while (len) {
! 990: sdla_bus_read_1(hw, offset++, (u_int8_t*)buf);
! 991: ((u_int8_t *)buf)++;
! 992: len--;
! 993: }
! 994: }
! 995:
! 996: /*
! 997: * Write Absolute Adapter Memory.
! 998: * Transfer data from data buffer to adapter's memory.
! 999: *
! 1000: * Note:
! 1001: * Care should be taken when crossing dual-port memory window boundary.
! 1002: * This function is not atomic, so caller must disable interrupt if
! 1003: * interrupt routines are accessing adapter shared memory.
! 1004: */
! 1005: int
! 1006: sdla_poke(void *phw, unsigned long addr, void *buf, unsigned len)
! 1007: {
! 1008: sdlahw_card_t* card = NULL;
! 1009: sdlahw_t* hw = (sdlahw_t*)phw;
! 1010: int err = 0;
! 1011:
! 1012: WAN_ASSERT(hw == NULL);
! 1013: SDLA_MAGIC(hw);
! 1014: WAN_ASSERT(hw->hwcard == NULL);
! 1015: card = hw->hwcard;
! 1016: if (addr + len > hw->memory) { /* verify arguments */
! 1017: return (EINVAL);
! 1018: }
! 1019:
! 1020: switch (card->type) {
! 1021: case SDLA_AFT:
! 1022: sdla_poke_by_4(hw, addr, buf, len);
! 1023: break;
! 1024:
! 1025: default:
! 1026: log(LOG_INFO, "%s: Invalid card type 0x%X\n",
! 1027: __FUNCTION__,card->type);
! 1028: err = (EINVAL);
! 1029: break;
! 1030: }
! 1031: return (err);
! 1032: }
! 1033:
! 1034:
! 1035: /*
! 1036: * Write from a data buffer to adapter's memory in 4-byte chunks.
! 1037: * Note that we ensure that the SDLA memory address is on a 4-byte boundary
! 1038: * before we begin moving the data in 4-byte chunks.
! 1039: */
! 1040: static void
! 1041: sdla_poke_by_4(sdlahw_t *hw, unsigned long offset, void *buf, unsigned int len)
! 1042: {
! 1043: /* byte copy data until we get to a 4-byte boundary */
! 1044: while (len && (offset & 0x03)) {
! 1045: sdla_bus_write_1(hw, offset++, *(char *)buf);
! 1046: ((char *)buf) ++;
! 1047: len --;
! 1048: }
! 1049:
! 1050: /* copy data in 4-byte chunks */
! 1051: while (len >= 4) {
! 1052: sdla_bus_write_4(hw, offset, *(unsigned long *)buf);
! 1053: offset += 4;
! 1054: (char*)buf += 4;
! 1055: len -= 4;
! 1056: }
! 1057:
! 1058: /* byte copy any remaining data */
! 1059: while (len) {
! 1060: sdla_bus_write_1(hw, offset++, *(char *)buf);
! 1061: ((char *)buf) ++;
! 1062: len --;
! 1063: }
! 1064: }
! 1065:
! 1066: int
! 1067: sdla_poke_byte(void *phw, unsigned long offset, u_int8_t value)
! 1068: {
! 1069: sdlahw_t *hw = (sdlahw_t*)phw;
! 1070:
! 1071: SDLA_MAGIC(hw);
! 1072: /* Sangoma ISA card sdla_bus_write_1(hw, offset, value); */
! 1073: sdla_poke(hw, offset, (void*)&value, 1);
! 1074: return (0);
! 1075: }
! 1076:
! 1077: int
! 1078: sdla_set_bit(void *phw, unsigned long offset, u_int8_t value)
! 1079: {
! 1080: sdlahw_t *hw = (sdlahw_t*)phw;
! 1081: u_int8_t tmp;
! 1082:
! 1083: SDLA_MAGIC(hw);
! 1084: /* Sangoma ISA card -> sdla_bus_read_1(hw, offset, &tmp); */
! 1085: sdla_peek(hw, offset, (void*)&tmp, 1);
! 1086: tmp |= value;
! 1087: /* Sangoma ISA card -> sdla_bus_write_1(hw, offset, tmp); */
! 1088: sdla_poke(hw, offset, (void*)&tmp, 1);
! 1089: return (0);
! 1090: }
! 1091:
! 1092: int
! 1093: sdla_clear_bit(void *phw, unsigned long offset, u_int8_t value)
! 1094: {
! 1095: sdlahw_t *hw = (sdlahw_t*)phw;
! 1096: u_int8_t tmp;
! 1097:
! 1098: SDLA_MAGIC(hw);
! 1099: /* Sangoma ISA card -> sdla_bus_read_1(hw, offset, &tmp); */
! 1100: sdla_peek(hw, offset, (void*)&tmp, 1);
! 1101: tmp &= ~value;
! 1102: /* Sangoma ISA card -> sdla_bus_write_1(hw, offset, tmp); */
! 1103: sdla_poke(hw, offset, (void*)&tmp, 1);
! 1104: return (0);
! 1105: }
! 1106:
! 1107: /*
! 1108: * Find the AFT HDLC PCI adapter in the PCI bus.
! 1109: * Return the number of AFT adapters found (0 if no adapter found).
! 1110: */
! 1111: static int
! 1112: sdla_detect_aft(sdlahw_t *hw)
! 1113: {
! 1114: sdlahw_card_t *card;
! 1115: u_int16_t ut_u16;
! 1116:
! 1117: WAN_ASSERT(hw == NULL);
! 1118: WAN_ASSERT(hw->hwcard == NULL);
! 1119: card = hw->hwcard;
! 1120: sdla_pci_read_config_dword(hw,
! 1121: (hw->cpu_no == SDLA_CPU_A) ? PCI_IO_BASE_DWORD :
! 1122: PCI_MEM_BASE0_DWORD, (u_int32_t*)&hw->mem_base_addr);
! 1123: if (!hw->mem_base_addr) {
! 1124: if (hw->cpu_no == SDLA_CPU_B) {
! 1125: printf("%s: No PCI memory allocated for CPU #B\n",
! 1126: hw->devname);
! 1127: } else {
! 1128: printf("%s: No PCI memory allocated to card\n",
! 1129: hw->devname);
! 1130: }
! 1131: return (EINVAL);
! 1132: }
! 1133: #ifdef DEBUG
! 1134: log(LOG_INFO, "%s: AFT PCI memory at 0x%lX\n",
! 1135: hw->devname, (unsigned long)hw->mem_base_addr);
! 1136: #endif /* DEBUG */
! 1137: sdla_pci_read_config_byte(hw, PCI_INTLINE, (u_int8_t*)&hw->irq);
! 1138: if (hw->irq == PCI_IRQ_NOT_ALLOCATED) {
! 1139: printf("%s: IRQ not allocated to AFT adapter\n", hw->devname);
! 1140: return (EINVAL);
! 1141: }
! 1142:
! 1143: #ifdef DEBUG
! 1144: log(LOG_INFO, "%s: IRQ %d allocated to the AFT PCI card\n",
! 1145: hw->devname, hw->irq);
! 1146: #endif /* DEBUG */
! 1147:
! 1148: hw->memory=XILINX_PCI_MEM_SIZE;
! 1149:
! 1150: /* Map the physical PCI memory to virtual memory */
! 1151: bus_space_map(hw->hwcard->memt, hw->mem_base_addr, XILINX_PCI_MEM_SIZE,
! 1152: 0, &hw->dpmbase);
! 1153: if (!hw->dpmbase) {
! 1154: printf("%s: couldn't map memory\n", hw->devname);
! 1155: return (EINVAL);
! 1156: }
! 1157: hw->status |= SDLA_MEM_MAPPED;
! 1158:
! 1159:
! 1160: /* Enable master operation on PCI and enable bar0 memory */
! 1161: sdla_pci_read_config_word(hw, XILINX_PCI_CMD_REG, &ut_u16);
! 1162: ut_u16 |=0x06;
! 1163: sdla_pci_write_config_word(hw, XILINX_PCI_CMD_REG, ut_u16);
! 1164:
! 1165: /* Set PCI Latency of 0xFF*/
! 1166: sdla_pci_write_config_dword(hw, XILINX_PCI_LATENCY_REG,
! 1167: XILINX_PCI_LATENCY);
! 1168:
! 1169: return (0);
! 1170: }
! 1171:
! 1172:
! 1173: /*
! 1174: * Detect adapter type.
! 1175: */
! 1176: static int
! 1177: sdla_detect(sdlahw_t *hw)
! 1178: {
! 1179: sdlahw_card_t *card = NULL;
! 1180: int err = 0;
! 1181:
! 1182: WAN_ASSERT(hw == NULL);
! 1183: WAN_ASSERT(hw->hwcard == NULL);
! 1184: card = hw->hwcard;
! 1185: switch (card->type) {
! 1186: case SDLA_AFT:
! 1187: err = sdla_detect_aft(hw);
! 1188: break;
! 1189: }
! 1190: if (err)
! 1191: sdla_down(hw);
! 1192:
! 1193: return (err);
! 1194: }
! 1195:
! 1196: int
! 1197: sdla_is_te1(void *phw)
! 1198: {
! 1199: sdlahw_card_t *hwcard = NULL;
! 1200: sdlahw_t *hw = (sdlahw_t*)phw;
! 1201:
! 1202: WAN_ASSERT(hw == NULL);
! 1203: SDLA_MAGIC(hw);
! 1204: WAN_ASSERT(hw->hwcard == NULL);
! 1205: hwcard = hw->hwcard;
! 1206: switch (hwcard->atype) {
! 1207: case S5144_ADPTR_1_CPU_T1E1:
! 1208: case S5147_ADPTR_2_CPU_T1E1:
! 1209: case S5148_ADPTR_1_CPU_T1E1:
! 1210: case A101_ADPTR_1TE1:
! 1211: case A101_ADPTR_2TE1:
! 1212: return (1);
! 1213: }
! 1214: return (0);
! 1215: }
! 1216:
! 1217: int
! 1218: sdla_check_mismatch(void *phw, unsigned char media)
! 1219: {
! 1220: sdlahw_card_t *hwcard = NULL;
! 1221: sdlahw_t *hw = (sdlahw_t*)phw;
! 1222:
! 1223: WAN_ASSERT(hw == NULL);
! 1224: SDLA_MAGIC(hw);
! 1225: WAN_ASSERT(hw->hwcard == NULL);
! 1226: hwcard = hw->hwcard;
! 1227: if (media == WAN_MEDIA_T1 ||
! 1228: media == WAN_MEDIA_E1) {
! 1229: if (hwcard->atype != S5144_ADPTR_1_CPU_T1E1 &&
! 1230: hwcard->atype != S5147_ADPTR_2_CPU_T1E1 &&
! 1231: hwcard->atype != S5148_ADPTR_1_CPU_T1E1) {
! 1232: log(LOG_INFO, "%s: Error: Card type mismatch: "
! 1233: "User=T1/E1 Actual=%s\n", hw->devname,
! 1234: SDLA_ADPTR_DECODE(hwcard->atype));
! 1235: return (EIO);
! 1236: }
! 1237: hwcard->atype = S5144_ADPTR_1_CPU_T1E1;
! 1238:
! 1239: } else if (media == WAN_MEDIA_56K) {
! 1240: if (hwcard->atype != S5145_ADPTR_1_CPU_56K) {
! 1241: log(LOG_INFO, "%s: Error: Card type mismatch: "
! 1242: "User=56K Actual=%s\n", hw->devname,
! 1243: SDLA_ADPTR_DECODE(hwcard->atype));
! 1244: return (EIO);
! 1245: }
! 1246: } else {
! 1247: if (hwcard->atype == S5145_ADPTR_1_CPU_56K ||
! 1248: hwcard->atype == S5144_ADPTR_1_CPU_T1E1 ||
! 1249: hwcard->atype == S5147_ADPTR_2_CPU_T1E1 ||
! 1250: hwcard->atype == S5148_ADPTR_1_CPU_T1E1) {
! 1251: log(LOG_INFO, "%s: Error: Card type mismatch: "
! 1252: "User=S514(1/2/3) Actual=%s\n", hw->devname,
! 1253: SDLA_ADPTR_DECODE(hwcard->atype));
! 1254: return (EIO);
! 1255: }
! 1256: }
! 1257:
! 1258: return (0);
! 1259: }
! 1260:
! 1261: int
! 1262: sdla_getcfg(void *phw, int type, void *value)
! 1263: {
! 1264: sdlahw_t* hw = (sdlahw_t*)phw;
! 1265: sdlahw_card_t *hwcard;
! 1266:
! 1267: WAN_ASSERT(hw == NULL);
! 1268: SDLA_MAGIC(hw);
! 1269: WAN_ASSERT(hw->hwcard == NULL);
! 1270: hwcard = hw->hwcard;
! 1271: switch (type) {
! 1272: case SDLA_CARDTYPE:
! 1273: *(u_int16_t*)value = hwcard->type;
! 1274: break;
! 1275: case SDLA_MEMBASE:
! 1276: *(bus_space_handle_t*)value = hw->dpmbase;
! 1277: break;
! 1278: case SDLA_MEMEND:
! 1279: *(u_int32_t*)value = ((unsigned long)hw->dpmbase +
! 1280: hw->dpmsize - 1);
! 1281: break;
! 1282: case SDLA_MEMSIZE:
! 1283: *(u_int16_t*)value = hw->dpmsize;
! 1284: break;
! 1285: case SDLA_MEMORY:
! 1286: *(u_int32_t*)value = hw->memory;
! 1287: break;
! 1288: case SDLA_IRQ:
! 1289: *(u_int16_t*)value = hw->irq;
! 1290: break;
! 1291: case SDLA_ADAPTERTYPE:
! 1292: *(u_int16_t*)value = hwcard->atype;
! 1293: break;
! 1294: case SDLA_CPU:
! 1295: *(u_int16_t*)value = hw->cpu_no;
! 1296: break;
! 1297: case SDLA_SLOT:
! 1298: *(u_int16_t*)value = hwcard->slot_no;
! 1299: break;
! 1300: case SDLA_BUS:
! 1301: *(u_int16_t*)value = hwcard->bus_no;
! 1302: break;
! 1303: case SDLA_DMATAG:
! 1304: *(bus_dma_tag_t*)value = hwcard->pa.pa_dmat;
! 1305: break;
! 1306: case SDLA_PCIEXTRAVER:
! 1307: *(u_int8_t*)value = hwcard->pci_extra_ver;
! 1308: break;
! 1309: case SDLA_BASEADDR:
! 1310: *(u_int32_t*)value = hw->mem_base_addr;
! 1311: break;
! 1312: }
! 1313: return (0);
! 1314: }
! 1315:
! 1316:
! 1317: int
! 1318: sdla_get_hwcard(void *phw, void **phwcard)
! 1319: {
! 1320: sdlahw_t *hw = (sdlahw_t*)phw;
! 1321:
! 1322: WAN_ASSERT(hw == NULL);
! 1323: SDLA_MAGIC(hw);
! 1324:
! 1325: *phwcard = hw->hwcard;
! 1326: return (0);
! 1327: }
! 1328:
! 1329:
! 1330: int
! 1331: sdla_get_hwprobe(void *phw, void **str)
! 1332: {
! 1333: sdlahw_t *hw = (sdlahw_t*)phw;
! 1334:
! 1335: WAN_ASSERT(hw == NULL);
! 1336: SDLA_MAGIC(hw);
! 1337:
! 1338: if (hw->hwprobe)
! 1339: *str = hw->hwprobe->hw_info;
! 1340:
! 1341: return (0);
! 1342: }
! 1343:
! 1344: int
! 1345: sdla_bus_write_1(void *phw, unsigned int offset, u_int8_t value)
! 1346: {
! 1347: sdlahw_t *hw = (sdlahw_t*)phw;
! 1348:
! 1349: WAN_ASSERT(hw == NULL);
! 1350: SDLA_MAGIC(hw);
! 1351: if (!(hw->status & SDLA_MEM_MAPPED))
! 1352: return (0);
! 1353: bus_space_write_1(hw->hwcard->memt, hw->dpmbase, offset, value);
! 1354: return (0);
! 1355: }
! 1356:
! 1357: int
! 1358: sdla_bus_write_2(void *phw, unsigned int offset, u_int16_t value)
! 1359: {
! 1360: sdlahw_t *hw = (sdlahw_t*)phw;
! 1361:
! 1362: WAN_ASSERT(hw == NULL);
! 1363: SDLA_MAGIC(hw);
! 1364: if (!(hw->status & SDLA_MEM_MAPPED))
! 1365: return (0);
! 1366: bus_space_write_2(hw->hwcard->memt, hw->dpmbase, offset, value);
! 1367: return (0);
! 1368: }
! 1369:
! 1370: int
! 1371: sdla_bus_write_4(void *phw, unsigned int offset, u_int32_t value)
! 1372: {
! 1373: sdlahw_t *hw = (sdlahw_t*)phw;
! 1374:
! 1375: WAN_ASSERT(hw == NULL);
! 1376: SDLA_MAGIC(hw);
! 1377: if (!(hw->status & SDLA_MEM_MAPPED))
! 1378: return (0);
! 1379: bus_space_write_4(hw->hwcard->memt, hw->dpmbase, offset, value);
! 1380: return (0);
! 1381: }
! 1382:
! 1383: int
! 1384: sdla_bus_read_1(void *phw, unsigned int offset, u_int8_t *value)
! 1385: {
! 1386: sdlahw_t *hw = (sdlahw_t*)phw;
! 1387:
! 1388: WAN_ASSERT2(hw == NULL, 0);
! 1389: SDLA_MAGIC(hw);
! 1390: if (!(hw->status & SDLA_MEM_MAPPED))
! 1391: return (0);
! 1392: *value = bus_space_read_1(hw->hwcard->memt, hw->dpmbase, offset);
! 1393: return (0);
! 1394: }
! 1395:
! 1396: int
! 1397: sdla_bus_read_2(void *phw, unsigned int offset, u_int16_t *value)
! 1398: {
! 1399: sdlahw_t *hw = (sdlahw_t*)phw;
! 1400:
! 1401: WAN_ASSERT2(hw == NULL, 0);
! 1402: SDLA_MAGIC(hw);
! 1403: if (!(hw->status & SDLA_MEM_MAPPED))
! 1404: return (0);
! 1405: *value = bus_space_read_2(hw->hwcard->memt, hw->dpmbase, offset);
! 1406: return (0);
! 1407: }
! 1408:
! 1409: int
! 1410: sdla_bus_read_4(void *phw, unsigned int offset, u_int32_t *value)
! 1411: {
! 1412: sdlahw_t *hw = (sdlahw_t*)phw;
! 1413:
! 1414: WAN_ASSERT2(hw == NULL, 0);
! 1415: WAN_ASSERT2(hw->dpmbase == 0, 0);
! 1416: SDLA_MAGIC(hw);
! 1417: if (!(hw->status & SDLA_MEM_MAPPED))
! 1418: return (0);
! 1419: *value = bus_space_read_4(hw->hwcard->memt, hw->dpmbase, offset);
! 1420: return (0);
! 1421: }
! 1422:
! 1423: static int
! 1424: sdla_pci_read_config_dword(void *phw, int reg, u_int32_t *value)
! 1425: {
! 1426: sdlahw_t *hw = (sdlahw_t*)phw;
! 1427: sdlahw_card_t *hwcard;
! 1428:
! 1429: WAN_ASSERT(hw == NULL);
! 1430: SDLA_MAGIC(hw);
! 1431: WAN_ASSERT(hw->hwcard == NULL);
! 1432: hwcard = hw->hwcard;
! 1433: *value = pci_conf_read(hwcard->pa.pa_pc, hwcard->pa.pa_tag, reg);
! 1434: return (0);
! 1435: }
! 1436:
! 1437: static int
! 1438: sdla_pci_read_config_word(void *phw, int reg, u_int16_t *value)
! 1439: {
! 1440: sdlahw_t *hw = (sdlahw_t*)phw;
! 1441: sdlahw_card_t *hwcard;
! 1442: u_int32_t tmp = 0x00;
! 1443:
! 1444: WAN_ASSERT(hw == NULL);
! 1445: SDLA_MAGIC(hw);
! 1446: WAN_ASSERT(hw->hwcard == NULL);
! 1447: hwcard = hw->hwcard;
! 1448: tmp = pci_conf_read(hwcard->pa.pa_pc, hwcard->pa.pa_tag, reg);
! 1449: *value = (u_int16_t)((tmp >> 16) & 0xFFFF);
! 1450: return (0);
! 1451: }
! 1452:
! 1453: static int
! 1454: sdla_pci_read_config_byte(void *phw, int reg, u_int8_t *value)
! 1455: {
! 1456: sdlahw_t *hw = (sdlahw_t*)phw;
! 1457: sdlahw_card_t *hwcard;
! 1458: u_int32_t tmp = 0x00;
! 1459:
! 1460: WAN_ASSERT(hw == NULL);
! 1461: SDLA_MAGIC(hw);
! 1462: WAN_ASSERT(hw->hwcard == NULL);
! 1463: hwcard = hw->hwcard;
! 1464: tmp = pci_conf_read(hwcard->pa.pa_pc, hwcard->pa.pa_tag, reg);
! 1465: *value = (u_int8_t)(tmp & 0xFF);
! 1466: return (0);
! 1467: }
! 1468:
! 1469: static int
! 1470: sdla_pci_write_config_dword(void *phw, int reg, u_int32_t value)
! 1471: {
! 1472: sdlahw_t *hw = (sdlahw_t*)phw;
! 1473: sdlahw_card_t *card;
! 1474:
! 1475: WAN_ASSERT(hw == NULL);
! 1476: SDLA_MAGIC(hw);
! 1477: WAN_ASSERT(hw->hwcard == NULL);
! 1478: card = hw->hwcard;
! 1479: pci_conf_write(card->pa.pa_pc, card->pa.pa_tag, reg, value);
! 1480: return (0);
! 1481: }
! 1482:
! 1483: static int
! 1484: sdla_pci_write_config_word(void *phw, int reg, u_int16_t value)
! 1485: {
! 1486: sdlahw_t *hw = (sdlahw_t*)phw;
! 1487: sdlahw_card_t *card;
! 1488:
! 1489: WAN_ASSERT(hw == NULL);
! 1490: SDLA_MAGIC(hw);
! 1491: WAN_ASSERT(hw->hwcard == NULL);
! 1492: card = hw->hwcard;
! 1493: pci_conf_write(card->pa.pa_pc, card->pa.pa_tag, reg, value);
! 1494: return (0);
! 1495: }
CVSweb