[BACK]Return to subr_hal.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / compat / ndis

Annotation of src/sys/compat/ndis/subr_hal.c, Revision 1.3.50.1

1.1       rittera     1: /*-
                      2:  * Copyright (c) 2003
                      3:  *     Bill Paul <wpaul@windriver.com>.  All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms, with or without
                      6:  * modification, are permitted provided that the following conditions
                      7:  * are met:
                      8:  * 1. Redistributions of source code must retain the above copyright
                      9:  *    notice, this list of conditions and the following disclaimer.
                     10:  * 2. Redistributions in binary form must reproduce the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer in the
                     12:  *    documentation and/or other materials provided with the distribution.
                     13:  * 3. All advertising materials mentioning features or use of this software
                     14:  *    must display the following acknowledgement:
                     15:  *     This product includes software developed by Bill Paul.
                     16:  * 4. Neither the name of the author nor the names of any co-contributors
                     17:  *    may be used to endorse or promote products derived from this software
                     18:  *    without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
                     21:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     22:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     23:  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
                     24:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     25:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     26:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     27:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     28:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     29:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     30:  * THE POSSIBILITY OF SUCH DAMAGE.
                     31:  */
                     32:
                     33: #include <sys/cdefs.h>
1.2       rittera    34: #ifdef __FreeBSD__
1.1       rittera    35: __FBSDID("$FreeBSD: src/sys/compat/ndis/subr_hal.c,v 1.13.2.3 2005/03/31 04:24:35 wpaul Exp $");
1.2       rittera    36: #endif
                     37: #ifdef __NetBSD__
                     38: __KERNEL_RCSID(0, "$NetBSD$");
                     39: #endif
1.1       rittera    40:
                     41: #include <sys/param.h>
                     42: #include <sys/types.h>
                     43: #include <sys/errno.h>
                     44:
                     45: #include <sys/callout.h>
                     46: #include <sys/kernel.h>
                     47: #include <sys/lock.h>
1.2       rittera    48: #ifdef __FreeBSD__
1.1       rittera    49: #include <sys/mutex.h>
1.2       rittera    50: #endif
1.1       rittera    51: #include <sys/proc.h>
                     52: #include <sys/sched.h>
1.2       rittera    53: #ifdef __FreeBSD__
1.1       rittera    54: #include <sys/module.h>
1.2       rittera    55: #endif
1.1       rittera    56:
                     57: #include <sys/systm.h>
1.2       rittera    58: #ifdef __NetBSD__
                     59: #include <sys/lkm.h>
                     60: #endif
                     61: #ifdef __FreeBSD__
1.1       rittera    62: #include <machine/clock.h>
                     63: #include <machine/bus_memio.h>
                     64: #include <machine/bus_pio.h>
1.2       rittera    65: #endif
1.3.50.1! bouyer     66: #include <sys/bus.h>
1.1       rittera    67:
1.2       rittera    68: #ifdef __FreeBSD__
1.1       rittera    69: #include <sys/bus.h>
                     70: #include <sys/rman.h>
1.2       rittera    71: #endif
1.1       rittera    72:
                     73: #include <compat/ndis/pe_var.h>
                     74: #include <compat/ndis/ntoskrnl_var.h>
                     75: #include <compat/ndis/hal_var.h>
                     76:
                     77: __stdcall static void KeStallExecutionProcessor(uint32_t);
                     78: __stdcall static void WRITE_PORT_BUFFER_ULONG(uint32_t *,
                     79:        uint32_t *, uint32_t);
                     80: __stdcall static void WRITE_PORT_BUFFER_USHORT(uint16_t *,
                     81:        uint16_t *, uint32_t);
                     82: __stdcall static void WRITE_PORT_BUFFER_UCHAR(uint8_t *,
                     83:        uint8_t *, uint32_t);
                     84: __stdcall static void WRITE_PORT_ULONG(uint32_t *, uint32_t);
                     85: __stdcall static void WRITE_PORT_USHORT(uint16_t *, uint16_t);
                     86: __stdcall static void WRITE_PORT_UCHAR(uint8_t *, uint8_t);
                     87: __stdcall static uint32_t READ_PORT_ULONG(uint32_t *);
                     88: __stdcall static uint16_t READ_PORT_USHORT(uint16_t *);
                     89: __stdcall static uint8_t READ_PORT_UCHAR(uint8_t *);
                     90: __stdcall static void READ_PORT_BUFFER_ULONG(uint32_t *,
                     91:        uint32_t *, uint32_t);
                     92: __stdcall static void READ_PORT_BUFFER_USHORT(uint16_t *,
                     93:        uint16_t *, uint32_t);
                     94: __stdcall static void READ_PORT_BUFFER_UCHAR(uint8_t *,
                     95:        uint8_t *, uint32_t);
                     96: __stdcall static uint64_t KeQueryPerformanceCounter(uint64_t *);
                     97: __stdcall static void dummy (void);
                     98:
                     99: extern struct mtx_pool *ndis_mtxpool;
                    100:
                    101: int
                    102: hal_libinit()
                    103: {
                    104:        image_patch_table       *patch;
                    105:
                    106:        patch = hal_functbl;
                    107:        while (patch->ipt_func != NULL) {
                    108:                windrv_wrap((funcptr)patch->ipt_func,
                    109:                    (funcptr *)&patch->ipt_wrap);
                    110:                patch++;
                    111:        }
                    112:
                    113:        return(0);
                    114: }
                    115:
                    116: int
                    117: hal_libfini()
                    118: {
                    119:        image_patch_table       *patch;
                    120:
                    121:        patch = hal_functbl;
                    122:        while (patch->ipt_func != NULL) {
                    123:                windrv_unwrap(patch->ipt_wrap);
                    124:                patch++;
                    125:        }
                    126:
                    127:        return(0);
                    128: }
                    129:
                    130: __stdcall static void
                    131: KeStallExecutionProcessor(usecs)
                    132:        uint32_t                usecs;
                    133: {
                    134:        DELAY(usecs);
                    135:        return;
                    136: }
                    137:
                    138: __stdcall static void
                    139: WRITE_PORT_ULONG(port, val)
                    140:        uint32_t                *port;
                    141:        uint32_t                val;
                    142: {
                    143:        bus_space_write_4(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val);
                    144:        return;
                    145: }
                    146:
                    147: __stdcall static void
                    148: WRITE_PORT_USHORT(port, val)
                    149:        uint16_t                *port;
                    150:        uint16_t                val;
                    151: {
                    152:        bus_space_write_2(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val);
                    153:        return;
                    154: }
                    155:
                    156: __stdcall static void
                    157: WRITE_PORT_UCHAR(port, val)
                    158:        uint8_t                 *port;
                    159:        uint8_t                 val;
                    160: {
                    161:        bus_space_write_1(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port, val);
                    162:        return;
                    163: }
                    164:
                    165: __stdcall static void
                    166: WRITE_PORT_BUFFER_ULONG(port, val, cnt)
                    167:        uint32_t                *port;
                    168:        uint32_t                *val;
                    169:        uint32_t                cnt;
                    170: {
                    171:        bus_space_write_multi_4(NDIS_BUS_SPACE_IO, 0x0,
                    172:            (bus_size_t)port, val, cnt);
                    173:        return;
                    174: }
                    175:
                    176: __stdcall static void
                    177: WRITE_PORT_BUFFER_USHORT(port, val, cnt)
                    178:        uint16_t                *port;
                    179:        uint16_t                *val;
                    180:        uint32_t                cnt;
                    181: {
                    182:        bus_space_write_multi_2(NDIS_BUS_SPACE_IO, 0x0,
                    183:            (bus_size_t)port, val, cnt);
                    184:        return;
                    185: }
                    186:
                    187: __stdcall static void
                    188: WRITE_PORT_BUFFER_UCHAR(port, val, cnt)
                    189:        uint8_t                 *port;
                    190:        uint8_t                 *val;
                    191:        uint32_t                cnt;
                    192: {
                    193:        bus_space_write_multi_1(NDIS_BUS_SPACE_IO, 0x0,
                    194:            (bus_size_t)port, val, cnt);
                    195:        return;
                    196: }
                    197:
                    198: __stdcall static uint16_t
                    199: READ_PORT_USHORT(port)
                    200:        uint16_t                *port;
                    201: {
                    202:        return(bus_space_read_2(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port));
                    203: }
                    204:
                    205: __stdcall static uint32_t
                    206: READ_PORT_ULONG(port)
                    207:        uint32_t                *port;
                    208: {
                    209:        return(bus_space_read_4(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port));
                    210: }
                    211:
                    212: __stdcall static uint8_t
                    213: READ_PORT_UCHAR(port)
                    214:        uint8_t                 *port;
                    215: {
                    216:        return(bus_space_read_1(NDIS_BUS_SPACE_IO, 0x0, (bus_size_t)port));
                    217: }
                    218:
                    219: __stdcall static void
                    220: READ_PORT_BUFFER_ULONG(port, val, cnt)
                    221:        uint32_t                *port;
                    222:        uint32_t                *val;
                    223:        uint32_t                cnt;
                    224: {
                    225:        bus_space_read_multi_4(NDIS_BUS_SPACE_IO, 0x0,
                    226:            (bus_size_t)port, val, cnt);
                    227:        return;
                    228: }
                    229:
                    230: __stdcall static void
                    231: READ_PORT_BUFFER_USHORT(port, val, cnt)
                    232:        uint16_t                *port;
                    233:        uint16_t                *val;
                    234:        uint32_t                cnt;
                    235: {
                    236:        bus_space_read_multi_2(NDIS_BUS_SPACE_IO, 0x0,
                    237:            (bus_size_t)port, val, cnt);
                    238:        return;
                    239: }
                    240:
                    241: __stdcall static void
                    242: READ_PORT_BUFFER_UCHAR(port, val, cnt)
                    243:        uint8_t                 *port;
                    244:        uint8_t                 *val;
                    245:        uint32_t                cnt;
                    246: {
                    247:        bus_space_read_multi_1(NDIS_BUS_SPACE_IO, 0x0,
                    248:            (bus_size_t)port, val, cnt);
                    249:        return;
                    250: }
                    251:
                    252: /*
                    253:  * The spinlock implementation in Windows differs from that of FreeBSD.
                    254:  * The basic operation of spinlocks involves two steps: 1) spin in a
                    255:  * tight loop while trying to acquire a lock, 2) after obtaining the
                    256:  * lock, disable preemption. (Note that on uniprocessor systems, you're
                    257:  * allowed to skip the first step and just lock out pre-emption, since
                    258:  * it's not possible for you to be in contention with another running
                    259:  * thread.) Later, you release the lock then re-enable preemption.
                    260:  * The difference between Windows and FreeBSD lies in how preemption
                    261:  * is disabled. In FreeBSD, it's done using critical_enter(), which on
                    262:  * the x86 arch translates to a cli instruction. This masks off all
                    263:  * interrupts, and effectively stops the scheduler from ever running
                    264:  * so _nothing_ can execute except the current thread. In Windows,
                    265:  * preemption is disabled by raising the processor IRQL to DISPATCH_LEVEL.
                    266:  * This stops other threads from running, but does _not_ block device
                    267:  * interrupts. This means ISRs can still run, and they can make other
                    268:  * threads runable, but those other threads won't be able to execute
                    269:  * until the current thread lowers the IRQL to something less than
                    270:  * DISPATCH_LEVEL.
                    271:  *
                    272:  * There's another commonly used IRQL in Windows, which is APC_LEVEL.
                    273:  * An APC is an Asynchronous Procedure Call, which differs from a DPC
                    274:  * (Defered Procedure Call) in that a DPC is queued up to run in
                    275:  * another thread, while an APC runs in the thread that scheduled
                    276:  * it (similar to a signal handler in a UNIX process). We don't
                    277:  * actually support the notion of APCs in FreeBSD, so for now, the
                    278:  * only IRQLs we're interested in are DISPATCH_LEVEL and PASSIVE_LEVEL.
                    279:  *
                    280:  * To simulate DISPATCH_LEVEL, we raise the current thread's priority
                    281:  * to PI_REALTIME, which is the highest we can give it. This should,
                    282:  * if I understand things correctly, prevent anything except for an
                    283:  * interrupt thread from preempting us. PASSIVE_LEVEL is basically
                    284:  * everything else.
                    285:  *
                    286:  * Be aware that, at least on the x86 arch, the Windows spinlock
                    287:  * functions are divided up in peculiar ways. The actual spinlock
                    288:  * functions are KfAcquireSpinLock() and KfReleaseSpinLock(), and
                    289:  * they live in HAL.dll. Meanwhile, KeInitializeSpinLock(),
                    290:  * KefAcquireSpinLockAtDpcLevel() and KefReleaseSpinLockFromDpcLevel()
                    291:  * live in ntoskrnl.exe. Most Windows source code will call
                    292:  * KeAcquireSpinLock() and KeReleaseSpinLock(), but these are just
                    293:  * macros that call KfAcquireSpinLock() and KfReleaseSpinLock().
                    294:  * KefAcquireSpinLockAtDpcLevel() and KefReleaseSpinLockFromDpcLevel()
                    295:  * perform the lock aquisition/release functions without doing the
                    296:  * IRQL manipulation, and are used when one is already running at
                    297:  * DISPATCH_LEVEL. Make sense? Good.
                    298:  *
                    299:  * According to the Microsoft documentation, any thread that calls
                    300:  * KeAcquireSpinLock() must be running at IRQL <= DISPATCH_LEVEL. If
                    301:  * we detect someone trying to acquire a spinlock from DEVICE_LEVEL
                    302:  * or HIGH_LEVEL, we panic.
                    303:  */
                    304:
                    305: __fastcall uint8_t
                    306: KfAcquireSpinLock(REGARGS1(kspin_lock *lock))
                    307: {
                    308:        uint8_t                 oldirql;
                    309:
                    310:        /* I am so going to hell for this. */
                    311:        if (KeGetCurrentIrql() > DISPATCH_LEVEL)
                    312:                panic("IRQL_NOT_LESS_THAN_OR_EQUAL");
                    313:
                    314:        oldirql = KeRaiseIrql(DISPATCH_LEVEL);
                    315:        KeAcquireSpinLockAtDpcLevel(lock);
                    316:
                    317:        return(oldirql);
                    318: }
                    319:
                    320: __fastcall void
                    321: KfReleaseSpinLock(REGARGS2(kspin_lock *lock, uint8_t newirql))
                    322: {
                    323:        KeReleaseSpinLockFromDpcLevel(lock);
                    324:        KeLowerIrql(newirql);
                    325:
                    326:        return;
                    327: }
                    328:
                    329: __stdcall uint8_t
                    330: KeGetCurrentIrql(void)
                    331: {
                    332:        if (AT_DISPATCH_LEVEL(curthread))
                    333:                return(DISPATCH_LEVEL);
                    334:        return(PASSIVE_LEVEL);
                    335: }
                    336:
                    337: __stdcall static uint64_t
                    338: KeQueryPerformanceCounter(freq)
                    339:        uint64_t                *freq;
                    340: {
                    341:        if (freq != NULL)
                    342:                *freq = hz;
                    343:
                    344:        return((uint64_t)ticks);
                    345: }
                    346:
1.3       rittera   347:
                    348: static int old_ipl;
                    349: static int ipl_raised = FALSE;
                    350:
1.1       rittera   351: __fastcall uint8_t
                    352: KfRaiseIrql(REGARGS1(uint8_t irql))
                    353: {
1.3       rittera   354:        uint8_t                 oldirql = 0;
                    355: //#ifdef __NetBSD__
                    356: //     uint8_t                 s;
                    357: //#endif
1.1       rittera   358:
                    359:        if (irql < KeGetCurrentIrql())
                    360:                panic("IRQL_NOT_LESS_THAN");
                    361:
                    362:        if (KeGetCurrentIrql() == DISPATCH_LEVEL)
                    363:                return(DISPATCH_LEVEL);
1.2       rittera   364: #ifdef __NetBSD__
1.3       rittera   365:        if(irql >= DISPATCH_LEVEL && !ipl_raised) {
                    366:                old_ipl = splsoftclock();
                    367:                ipl_raised = TRUE;
                    368:                oldirql = win_irql;
                    369:                win_irql = irql;
                    370:        }
                    371: #else /* __FreeBSD__ */
1.1       rittera   372:        mtx_lock_spin(&sched_lock);
                    373:        oldirql = curthread->td_base_pri;
                    374:        sched_prio(curthread, PI_REALTIME);
                    375: #if __FreeBSD_version < 600000
                    376:        curthread->td_base_pri = PI_REALTIME;
                    377: #endif
                    378:        mtx_unlock_spin(&sched_lock);
1.3       rittera   379: #endif /* __FreeBSD__ */
1.1       rittera   380:
                    381:        return(oldirql);
                    382: }
                    383:
                    384: __fastcall void
                    385: KfLowerIrql(REGARGS1(uint8_t oldirql))
                    386: {
1.3       rittera   387: //#ifdef __NetBSD__
                    388: //     uint8_t         s;
                    389: //#endif
1.2       rittera   390:
1.1       rittera   391:        if (oldirql == DISPATCH_LEVEL)
                    392:                return;
                    393:
1.3       rittera   394: #ifdef __FreeBSD__
1.1       rittera   395:        if (KeGetCurrentIrql() != DISPATCH_LEVEL)
                    396:                panic("IRQL_NOT_GREATER_THAN");
1.3       rittera   397: #else /* __NetBSD__ */
                    398:        if (KeGetCurrentIrql() < oldirql)
                    399:                panic("IRQL_NOT_GREATER_THAN");
                    400: #endif
1.1       rittera   401:
1.2       rittera   402: #ifdef __NetBSD__
1.3       rittera   403:        if(oldirql < DISPATCH_LEVEL && ipl_raised) {
                    404:                splx(old_ipl);
                    405:                ipl_raised = FALSE;
                    406:                win_irql = oldirql;
                    407:        }
1.2       rittera   408: #else
1.1       rittera   409:        mtx_lock_spin(&sched_lock);
                    410: #if __FreeBSD_version < 600000
                    411:        curthread->td_base_pri = oldirql;
                    412: #endif
                    413:        sched_prio(curthread, oldirql);
                    414:        mtx_unlock_spin(&sched_lock);
1.2       rittera   415: #endif /* __NetBSD__ */
1.1       rittera   416:
                    417:        return;
                    418: }
                    419:
                    420: __stdcall
                    421: static void dummy()
                    422: {
                    423:        printf ("hal dummy called...\n");
                    424:        return;
                    425: }
                    426:
                    427: image_patch_table hal_functbl[] = {
                    428:        IMPORT_FUNC(KeStallExecutionProcessor),
                    429:        IMPORT_FUNC(WRITE_PORT_ULONG),
                    430:        IMPORT_FUNC(WRITE_PORT_USHORT),
                    431:        IMPORT_FUNC(WRITE_PORT_UCHAR),
                    432:        IMPORT_FUNC(WRITE_PORT_BUFFER_ULONG),
                    433:        IMPORT_FUNC(WRITE_PORT_BUFFER_USHORT),
                    434:        IMPORT_FUNC(WRITE_PORT_BUFFER_UCHAR),
                    435:        IMPORT_FUNC(READ_PORT_ULONG),
                    436:        IMPORT_FUNC(READ_PORT_USHORT),
                    437:        IMPORT_FUNC(READ_PORT_UCHAR),
                    438:        IMPORT_FUNC(READ_PORT_BUFFER_ULONG),
                    439:        IMPORT_FUNC(READ_PORT_BUFFER_USHORT),
                    440:        IMPORT_FUNC(READ_PORT_BUFFER_UCHAR),
                    441:        IMPORT_FUNC(KfAcquireSpinLock),
                    442:        IMPORT_FUNC(KfReleaseSpinLock),
                    443:        IMPORT_FUNC(KeGetCurrentIrql),
                    444:        IMPORT_FUNC(KeQueryPerformanceCounter),
                    445:        IMPORT_FUNC(KfLowerIrql),
                    446:        IMPORT_FUNC(KfRaiseIrql),
                    447:
                    448:        /*
                    449:         * This last entry is a catch-all for any function we haven't
                    450:         * implemented yet. The PE import list patching routine will
                    451:         * use it for any function that doesn't have an explicit match
                    452:         * in this table.
                    453:         */
                    454:
                    455:        { NULL, (FUNC)dummy, NULL },
                    456:
                    457:        /* End of list. */
                    458:
                    459:        { NULL, NULL, NULL }
                    460: };

CVSweb <webmaster@jp.NetBSD.org>