[BACK]Return to if_sandrv.c CVS log [TXT][DIR] Up to [local] / sys / dev / pci

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