root/arch/i386/include/bus.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


    1 /*      $OpenBSD: bus.h,v 1.40 2007/02/20 21:15:01 tom Exp $    */
    2 /*      $NetBSD: bus.h,v 1.6 1996/11/10 03:19:25 thorpej Exp $  */
    3 
    4 /*-
    5  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
   10  * NASA Ames Research Center.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. All advertising materials mentioning features or use of this software
   21  *    must display the following acknowledgement:
   22  *      This product includes software developed by the NetBSD
   23  *      Foundation, Inc. and its contributors.
   24  * 4. Neither the name of The NetBSD Foundation nor the names of its
   25  *    contributors may be used to endorse or promote products derived
   26  *    from this software without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   29  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   31  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   32  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   38  * POSSIBILITY OF SUCH DAMAGE.
   39  */
   40 
   41 /*
   42  * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
   43  * Copyright (c) 1996 Jason R. Thorpe.  All rights reserved.
   44  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
   45  *
   46  * Redistribution and use in source and binary forms, with or without
   47  * modification, are permitted provided that the following conditions
   48  * are met:
   49  * 1. Redistributions of source code must retain the above copyright
   50  *    notice, this list of conditions and the following disclaimer.
   51  * 2. Redistributions in binary form must reproduce the above copyright
   52  *    notice, this list of conditions and the following disclaimer in the
   53  *    documentation and/or other materials provided with the distribution.
   54  * 3. All advertising materials mentioning features or use of this software
   55  *    must display the following acknowledgement:
   56  *      This product includes software developed by Christopher G. Demetriou
   57  *      for the NetBSD Project.
   58  * 4. The name of the author may not be used to endorse or promote products
   59  *    derived from this software without specific prior written permission
   60  *
   61  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   62  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   63  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   64  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   65  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   66  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   67  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   68  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   69  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   70  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   71  */
   72 
   73 #ifndef _I386_BUS_H_
   74 #define _I386_BUS_H_
   75 
   76 #include <machine/pio.h>
   77 
   78 /*
   79  * Values for the i386 bus space tag, not to be used directly by MI code.
   80  */
   81 #define I386_BUS_SPACE_IO       0       /* space is i/o space */
   82 #define I386_BUS_SPACE_MEM      1       /* space is mem space */
   83 
   84 /*
   85  * Bus address and size types
   86  */
   87 typedef u_long bus_addr_t;
   88 typedef u_long bus_size_t;
   89 
   90 /*
   91  * Access methods for bus resources and address space.
   92  */
   93 typedef int bus_space_tag_t;
   94 typedef u_long bus_space_handle_t;
   95 
   96 int     bus_space_map(bus_space_tag_t t, bus_addr_t addr,
   97             bus_size_t size, int cacheable, bus_space_handle_t *bshp);
   98 /* like bus_space_map(), but without extent map checking/allocation */
   99 int     _bus_space_map(bus_space_tag_t t, bus_addr_t addr,
  100             bus_size_t size, int cacheable, bus_space_handle_t *bshp);
  101 void    bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
  102             bus_size_t size);
  103 /* like bus_space_unmap(), but without extent map deallocation */
  104 void    _bus_space_unmap(bus_space_tag_t, bus_space_handle_t,
  105             bus_size_t, bus_addr_t *);
  106 int     bus_space_subregion(bus_space_tag_t t, bus_space_handle_t bsh,
  107             bus_size_t offset, bus_size_t size, bus_space_handle_t *nbshp);
  108 
  109 int     bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
  110             bus_addr_t rend, bus_size_t size, bus_size_t align,
  111             bus_size_t boundary, int cacheable, bus_addr_t *addrp,
  112             bus_space_handle_t *bshp);
  113 void    bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
  114             bus_size_t size);
  115 
  116 /*
  117  *      u_intN_t bus_space_read_N(bus_space_tag_t tag,
  118  *          bus_space_handle_t bsh, bus_size_t offset);
  119  *
  120  * Read a 1, 2, 4, or 8 byte quantity from bus space
  121  * described by tag/handle/offset.
  122  */
  123 
  124 #define bus_space_read_1(t, h, o)                                       \
  125         ((t) == I386_BUS_SPACE_IO ? (inb((h) + (o))) :                  \
  126             (*(volatile u_int8_t *)((h) + (o))))
  127 
  128 #define bus_space_read_2(t, h, o)                                       \
  129         ((t) == I386_BUS_SPACE_IO ? (inw((h) + (o))) :                  \
  130             (*(volatile u_int16_t *)((h) + (o))))
  131 
  132 #define bus_space_read_4(t, h, o)                                       \
  133         ((t) == I386_BUS_SPACE_IO ? (inl((h) + (o))) :                  \
  134             (*(volatile u_int32_t *)((h) + (o))))
  135 
  136 #if 0   /* Cause a link error for bus_space_read_8 */
  137 #define bus_space_read_8(t, h, o)       !!! bus_space_read_8 unimplemented !!!
  138 #endif
  139 
  140 /*
  141  *      void bus_space_read_multi_N(bus_space_tag_t tag,
  142  *          bus_space_handle_t bsh, bus_size_t offset,
  143  *          u_intN_t *addr, size_t count);
  144  *
  145  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
  146  * described by tag/handle/offset and copy into buffer provided.
  147  */
  148 
  149 #define bus_space_read_multi_1(t, h, o, a, cnt) do {                    \
  150         if ((t) == I386_BUS_SPACE_IO) {                                 \
  151                 insb((h) + (o), (a), (cnt));                            \
  152         } else {void *_addr=(a); int _cnt=(cnt);                        \
  153                 __asm __volatile("                                      \
  154                         cld                                     ;       \
  155                 1:      movb (%2),%%al                          ;       \
  156                         stosb                                   ;       \
  157                         loop 1b"                                :       \
  158                     "+D" (_addr), "+c" (_cnt) : "r" ((h) + (o)) :       \
  159                     "%eax", "memory", "cc");                            \
  160         }                                                               \
  161 } while (0)
  162 
  163 #define bus_space_read_multi_2(t, h, o, a, cnt) do {                    \
  164         if ((t) == I386_BUS_SPACE_IO) {                                 \
  165                 insw((h) + (o), (a), (cnt));                            \
  166         } else {void *_addr=(a); int _cnt=(cnt);                        \
  167                 __asm __volatile("                                      \
  168                         cld                                     ;       \
  169                 1:      movw (%2),%%ax                          ;       \
  170                         stosw                                   ;       \
  171                         loop 1b"                                :       \
  172                     "+D" (_addr), "+c" (_cnt) : "r" ((h) + (o)) :       \
  173                     "%eax", "memory", "cc");                            \
  174         }                                                               \
  175 } while (0)
  176 
  177 #define bus_space_read_multi_4(t, h, o, a, cnt) do {                    \
  178         if ((t) == I386_BUS_SPACE_IO) {                                 \
  179                 insl((h) + (o), (a), (cnt));                            \
  180         } else {void *_addr=(a); int _cnt=(cnt);                        \
  181                 __asm __volatile("                                      \
  182                         cld                                     ;       \
  183                 1:      movl (%2),%%eax                         ;       \
  184                         stosl                                   ;       \
  185                         loop 1b"                                :       \
  186                     "+D" (_addr), "+c" (_cnt) : "r" ((h) + (o)) :       \
  187                     "%eax", "memory", "cc");                            \
  188         }                                                               \
  189 } while (0)
  190 
  191 #if 0   /* Cause a link error for bus_space_read_multi_8 */
  192 #define bus_space_read_multi_8  !!! bus_space_read_multi_8 unimplemented !!!
  193 #endif
  194 
  195 /*
  196  *      void bus_space_read_raw_multi_N(bus_space_tag_t tag,
  197  *          bus_space_handle_t bsh, bus_size_t offset,
  198  *          u_int8_t *addr, size_t count);
  199  *
  200  * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
  201  * described by tag/handle/offset and copy into buffer provided.  The buffer
  202  * must have proper alignment for the N byte wide entities.  Furthermore
  203  * possible byte-swapping should be done by these functions.
  204  */
  205 
  206 #define bus_space_read_raw_multi_2(t, h, o, a, c) \
  207     bus_space_read_multi_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1)
  208 #define bus_space_read_raw_multi_4(t, h, o, a, c) \
  209     bus_space_read_multi_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2)
  210 
  211 #if 0   /* Cause a link error for bus_space_read_raw_multi_8 */
  212 #define bus_space_read_raw_multi_8 \
  213     !!! bus_space_read_raw_multi_8 unimplemented !!!
  214 #endif
  215 
  216 /*
  217  *      void bus_space_read_region_N(bus_space_tag_t tag,
  218  *          bus_space_handle_t bsh, bus_size_t offset,
  219  *          u_intN_t *addr, size_t count);
  220  *
  221  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
  222  * described by tag/handle and starting at `offset' and copy into
  223  * buffer provided.
  224  */
  225 
  226 #define bus_space_read_region_1(t, h, o, a, cnt) do {                   \
  227         int _cnt = (cnt);       void *_addr = (a); int _port = (h)+(o); \
  228         if ((t) == I386_BUS_SPACE_IO) {                                 \
  229                 __asm __volatile("                                      \
  230                         cld                                     ;       \
  231                 1:      inb %w2,%%al                            ;       \
  232                         stosb                                   ;       \
  233                         incl %2                                 ;       \
  234                         loop 1b"                                :       \
  235                     "+D" (_addr), "+c" (_cnt), "+d" (_port)     ::      \
  236                     "%eax", "memory", "cc");                            \
  237         } else                                                          \
  238                 i386_space_copy(_port, _addr, 1, _cnt);                 \
  239 } while (0)
  240 
  241 #define bus_space_read_region_2(t, h, o, a, cnt) do {                   \
  242         int _cnt = (cnt);       void *_addr = (a); int _port = (h)+(o); \
  243         if ((t) == I386_BUS_SPACE_IO) {                                 \
  244                 __asm __volatile("                                      \
  245                         cld                                     ;       \
  246                 1:      inw %w2,%%ax                            ;       \
  247                         stosw                                   ;       \
  248                         addl $2,%2                              ;       \
  249                         loop 1b"                                :       \
  250                     "+D" (_addr), "+c" (_cnt), "+d" (_port)     ::      \
  251                     "%eax", "memory", "cc");                            \
  252         } else                                                          \
  253                 i386_space_copy(_port, _addr, 2, _cnt);                 \
  254 } while (0)
  255 
  256 #define bus_space_read_region_4(t, h, o, a, cnt) do {                   \
  257         int _cnt = (cnt);       void *_addr = (a); int _port = (h)+(o); \
  258         if ((t) == I386_BUS_SPACE_IO) {                                 \
  259                 __asm __volatile("                                      \
  260                         cld                                     ;       \
  261                 1:      inl %w2,%%eax                           ;       \
  262                         stosl                                   ;       \
  263                         addl $4,%2                              ;       \
  264                         loop 1b"                                :       \
  265                     "+D" (_addr), "+c" (_cnt), "+d" (_port)     ::      \
  266                     "%eax", "memory", "cc");                            \
  267         } else                                                          \
  268                 i386_space_copy(_port, _addr, 4, _cnt);                 \
  269 } while (0)
  270 
  271 #if 0   /* Cause a link error for bus_space_read_region_8 */
  272 #define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!!
  273 #endif
  274 
  275 /*
  276  *      void bus_space_read_raw_region_N(bus_space_tag_t tag,
  277  *          bus_space_handle_t bsh, bus_size_t offset,
  278  *          u_int8_t *addr, size_t count);
  279  *
  280  * Read `count' bytes in 2, 4 or 8 byte wide quantities from bus space
  281  * described by tag/handle and starting at `offset' and copy into
  282  * buffer provided.  The buffer must have proper alignment for the N byte
  283  * wide entities.  Furthermore possible byte-swapping should be done by
  284  * these functions.
  285  */
  286 
  287 #define bus_space_read_raw_region_2(t, h, o, a, c) \
  288     bus_space_read_region_2((t), (h), (o), (u_int16_t *)(a), (c) >> 1)
  289 #define bus_space_read_raw_region_4(t, h, o, a, c) \
  290     bus_space_read_region_4((t), (h), (o), (u_int32_t *)(a), (c) >> 2)
  291 
  292 #if 0   /* Cause a link error for bus_space_read_raw_region_8 */
  293 #define bus_space_read_raw_region_8 \
  294     !!! bus_space_read_raw_region_8 unimplemented !!!
  295 #endif
  296 
  297 /*
  298  *      void bus_space_write_N(bus_space_tag_t tag,
  299  *          bus_space_handle_t bsh, bus_size_t offset,
  300  *          u_intN_t value);
  301  *
  302  * Write the 1, 2, 4, or 8 byte value `value' to bus space
  303  * described by tag/handle/offset.
  304  */
  305 
  306 #define bus_space_write_1(t, h, o, v)   do {                            \
  307         if ((t) == I386_BUS_SPACE_IO)                                   \
  308                 outb((h) + (o), (v));                                   \
  309         else                                                            \
  310                 ((void)(*(volatile u_int8_t *)((h) + (o)) = (v)));      \
  311 } while (0)
  312 
  313 #define bus_space_write_2(t, h, o, v)   do {                            \
  314         if ((t) == I386_BUS_SPACE_IO)                                   \
  315                 outw((h) + (o), (v));                                   \
  316         else                                                            \
  317                 ((void)(*(volatile u_int16_t *)((h) + (o)) = (v)));     \
  318 } while (0)
  319 
  320 #define bus_space_write_4(t, h, o, v)   do {                            \
  321         if ((t) == I386_BUS_SPACE_IO)                                   \
  322                 outl((h) + (o), (v));                                   \
  323         else                                                            \
  324                 ((void)(*(volatile u_int32_t *)((h) + (o)) = (v)));     \
  325 } while (0)
  326 
  327 #if 0   /* Cause a link error for bus_space_write_8 */
  328 #define bus_space_write_8       !!! bus_space_write_8 not implemented !!!
  329 #endif
  330 
  331 /*
  332  *      void bus_space_write_multi_N(bus_space_tag_t tag,
  333  *          bus_space_handle_t bsh, bus_size_t offset,
  334  *          const u_intN_t *addr, size_t count);
  335  *
  336  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
  337  * provided to bus space described by tag/handle/offset.
  338  */
  339 
  340 #define bus_space_write_multi_1(t, h, o, a, cnt) do {                   \
  341         if ((t) == I386_BUS_SPACE_IO) {                                 \
  342                 outsb((h) + (o), (a), (cnt));                           \
  343         } else {const void *_addr=(a); int _cnt=(cnt);                  \
  344                 __asm __volatile("                                      \
  345                         cld                                     ;       \
  346                 1:      lodsb                                   ;       \
  347                         movb %%al,(%2)                          ;       \
  348                         loop 1b"                                :       \
  349                     "+S" (_addr), "+c" (_cnt) : "r" ((h) + (o)) :       \
  350                     "%eax", "memory", "cc");                            \
  351         }                                                               \
  352 } while (0)
  353 
  354 #define bus_space_write_multi_2(t, h, o, a, cnt) do {                   \
  355         if ((t) == I386_BUS_SPACE_IO) {                                 \
  356                 outsw((h) + (o), (a), (cnt));                           \
  357         } else {const void *_addr=(a); int _cnt=(cnt);                  \
  358                 __asm __volatile("                                      \
  359                         cld                                     ;       \
  360                 1:      lodsw                                   ;       \
  361                         movw %%ax,(%2)                          ;       \
  362                         loop 1b"                                :       \
  363                     "+S" (_addr), "+c" (_cnt) : "r" ((h) + (o)) :       \
  364                     "%eax", "memory", "cc");                            \
  365         }                                                               \
  366 } while (0)
  367 
  368 #define bus_space_write_multi_4(t, h, o, a, cnt) do {                   \
  369         if ((t) == I386_BUS_SPACE_IO) {                                 \
  370                 outsl((h) + (o), (a), (cnt));                           \
  371         } else {const void *_addr=(a); int _cnt=(cnt);                  \
  372                 __asm __volatile("                                      \
  373                         cld                                     ;       \
  374                 1:      lodsl                                   ;       \
  375                         movl %%eax,(%2)                         ;       \
  376                         loop 1b"                                :       \
  377                     "+S" (_addr), "+c" (_cnt) : "r" ((h) + (o)) :       \
  378                     "%eax", "memory", "cc");                            \
  379         }                                                               \
  380 } while (0)
  381 
  382 #if 0   /* Cause a link error for bus_space_write_multi_8 */
  383 #define bus_space_write_multi_8(t, h, o, a, c)                          \
  384                         !!! bus_space_write_multi_8 unimplemented !!!
  385 #endif
  386 
  387 /*
  388  *      void bus_space_write_raw_multi_N(bus_space_tag_t tag,
  389  *          bus_space_handle_t bsh, bus_size_t offset,
  390  *          const u_int8_t *addr, size_t count);
  391  *
  392  * Write `count' bytes in 2, 4 or 8 byte wide quantities from the buffer
  393  * provided to bus space described by tag/handle/offset.  The buffer
  394  * must have proper alignment for the N byte wide entities.  Furthermore
  395  * possible byte-swapping should be done by these functions.
  396  */
  397 
  398 #define bus_space_write_raw_multi_2(t, h, o, a, c) \
  399     bus_space_write_multi_2((t), (h), (o), (const u_int16_t *)(a), (c) >> 1)
  400 #define bus_space_write_raw_multi_4(t, h, o, a, c) \
  401     bus_space_write_multi_4((t), (h), (o), (const u_int32_t *)(a), (c) >> 2)
  402 
  403 #if 0   /* Cause a link error for bus_space_write_raw_multi_8 */
  404 #define bus_space_write_raw_multi_8 \
  405     !!! bus_space_write_raw_multi_8 unimplemented !!!
  406 #endif
  407 
  408 /*
  409  *      void bus_space_write_region_N(bus_space_tag_t tag,
  410  *          bus_space_handle_t bsh, bus_size_t offset,
  411  *          const u_intN_t *addr, size_t count);
  412  *
  413  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
  414  * to bus space described by tag/handle starting at `offset'.
  415  */
  416 
  417 #define bus_space_write_region_1(t, h, o, a, cnt) do {                  \
  418         int _port = (h)+(o); const void *_addr=(a); int _cnt=(cnt);     \
  419         if ((t) == I386_BUS_SPACE_IO) {                                 \
  420                 __asm __volatile("                                      \
  421                         cld                                     ;       \
  422                 1:      lodsb                                   ;       \
  423                         outb %%al,%w0                           ;       \
  424                         incl %0                                 ;       \
  425                         loop 1b"                                :       \
  426                     "+d" (_port), "+S" (_addr), "+c" (_cnt)     ::      \
  427                     "%eax", "memory", "cc");                            \
  428         } else                                                          \
  429                 i386_space_copy(_addr, _port, 1, _cnt);                 \
  430 } while (0)
  431 
  432 #define bus_space_write_region_2(t, h, o, a, cnt) do {                  \
  433         int _port = (h)+(o); const void *_addr=(a); int _cnt=(cnt);     \
  434         if ((t) == I386_BUS_SPACE_IO) {                                 \
  435                 __asm __volatile("                                      \
  436                         cld                                     ;       \
  437                 1:      lodsw                                   ;       \
  438                         outw %%ax,%w0                           ;       \
  439                         addl $2,%0                              ;       \
  440                         loop 1b"                                :       \
  441                     "+d" (_port), "+S" (_addr), "+c" (_cnt)     ::      \
  442                     "%eax", "memory", "cc");                            \
  443         } else                                                          \
  444                 i386_space_copy(_addr, _port, 2, _cnt);                 \
  445 } while (0)
  446 
  447 #define bus_space_write_region_4(t, h, o, a, cnt) do {                  \
  448         int _port = (h)+(o); const void *_addr=(a); int _cnt=(cnt);     \
  449         if ((t) == I386_BUS_SPACE_IO) {                                 \
  450                 __asm __volatile("                                      \
  451                         cld                                     ;       \
  452                 1:      lodsl                                   ;       \
  453                         outl %%eax,%w0                          ;       \
  454                         addl $4,%0                              ;       \
  455                         loop 1b"                                :       \
  456                     "+d" (_port), "+S" (_addr), "+c" (_cnt)     ::      \
  457                     "%eax", "memory", "cc");                            \
  458         } else                                                          \
  459                 i386_space_copy(_addr, _port, 4, _cnt);                 \
  460 } while (0)
  461 
  462 #if 0   /* Cause a link error for bus_space_write_region_8 */
  463 #define bus_space_write_region_8                                        \
  464                         !!! bus_space_write_region_8 unimplemented !!!
  465 #endif
  466 
  467 /*
  468  *      void bus_space_write_raw_region_N(bus_space_tag_t tag,
  469  *          bus_space_handle_t bsh, bus_size_t offset,
  470  *          const u_int8_t *addr, size_t count);
  471  *
  472  * Write `count' bytes in 2, 4 or 8 byte wide quantities to bus space
  473  * described by tag/handle and starting at `offset' from the
  474  * buffer provided.  The buffer must have proper alignment for the N byte
  475  * wide entities.  Furthermore possible byte-swapping should be done by
  476  * these functions.
  477  */
  478 
  479 #define bus_space_write_raw_region_2(t, h, o, a, c) \
  480     bus_space_write_region_2((t), (h), (o), (const u_int16_t *)(a), (c) >> 1)
  481 #define bus_space_write_raw_region_4(t, h, o, a, c) \
  482     bus_space_write_region_4((t), (h), (o), (const u_int32_t *)(a), (c) >> 2)
  483 
  484 #if 0   /* Cause a link error for bus_space_write_raw_region_8 */
  485 #define bus_space_write_raw_region_8 \
  486     !!! bus_space_write_raw_region_8 unimplemented !!!
  487 #endif
  488 
  489 /*
  490  *      void bus_space_set_multi_N(bus_space_tag_t tag,
  491  *          bus_space_handle_t bsh, bus_size_t offset,
  492  *          u_intN_t val, size_t count);
  493  *
  494  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
  495  * by tag/handle/offset `count' times.
  496  */
  497 
  498 #define bus_space_set_multi_1(t, h, o, v, cnt) do {                     \
  499         int _cnt=(cnt);                                                 \
  500         if ((t) == I386_BUS_SPACE_IO) {                                 \
  501                 __asm __volatile("                                      \
  502                         cld                                     ;       \
  503                 1:      outb %b2, %w1                           ;       \
  504                         loop 1b"                                :       \
  505                     "+c" (_cnt) : "d" ((h) + (o)), "a" ((v))    :       \
  506                     "cc");                                              \
  507         } else {                                                        \
  508                 __asm __volatile("                                      \
  509                         cld                                     ;       \
  510                 1:      movb %b2, (%1)                          ;       \
  511                         loop 1b"                                :       \
  512                     "+c" (_cnt) : "D" ((h) + (o)), "a" ((v))    :       \
  513                     "cc", "memory");                                    \
  514         }                                                               \
  515 } while (0)
  516 
  517 #define bus_space_set_multi_2(t, h, o, v, cnt) do {                     \
  518         int _cnt=(cnt);                                                 \
  519         if ((t) == I386_BUS_SPACE_IO) {                                 \
  520                 __asm __volatile("                                      \
  521                         cld                                     ;       \
  522                 1:      outw %w2, %w1                           ;       \
  523                         loop 1b"                                :       \
  524                     "+c" (_cnt) : "d" ((h) + (o)), "a" ((v))    :       \
  525                     "cc");                                              \
  526         } else {                                                        \
  527                 __asm __volatile("                                      \
  528                         cld                                     ;       \
  529                 1:      movw %w2, (%1)                          ;       \
  530                         loop 1b"                                :       \
  531                     "+c" (_cnt) : "D" ((h) + (o)), "a" ((v))    :       \
  532                     "cc", "memory");                                    \
  533         }                                                               \
  534 } while (0)
  535 
  536 #define bus_space_set_multi_4(t, h, o, v, cnt) do {                     \
  537         int _cnt=(cnt);                                                 \
  538         if ((t) == I386_BUS_SPACE_IO) {                                 \
  539                 __asm __volatile("                                      \
  540                         cld                                     ;       \
  541                 1:      outl %2,%w1                             ;       \
  542                         loop 1b"                                :       \
  543                     "+c" (_cnt) : "d" ((h) + (o)), "a" ((v))    :       \
  544                     "cc");                                              \
  545         } else {                                                        \
  546                 __asm __volatile("                                      \
  547                         cld                                     ;       \
  548                 1:      movl %2,(%1)                            ;       \
  549                         loop 1b"                                :       \
  550                     "+c" (_cnt) : "D" ((h) + (o)), "a" ((v))    :       \
  551                     "cc", "memory");                                    \
  552         }                                                               \
  553 } while (0)
  554 
  555 #if 0   /* Cause a link error for bus_space_set_multi_8 */
  556 #define bus_space_set_multi_8                                   \
  557                         !!! bus_space_set_multi_8 unimplemented !!!
  558 #endif
  559 
  560 /*
  561  *      void bus_space_set_region_N(bus_space_tag_t tag,
  562  *          bus_space_handle_t bsh, bus_size_t offset,
  563  *          u_intN_t val, size_t count);
  564  *
  565  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
  566  * by tag/handle starting at `offset'.
  567  */
  568 
  569 #define bus_space_set_region_1(t, h, o, v, cnt) do {                    \
  570         int _port = (h)+(o); int _cnt = (cnt);                          \
  571         if ((t) == I386_BUS_SPACE_IO) {                                 \
  572                 __asm __volatile("                                      \
  573                 1:      outb %%al,%w0                           ;       \
  574                         incl %0                                 ;       \
  575                         loop 1b"                                :       \
  576                     "+d" (_port), "+c" (_cnt) : "a" ((v))       :       \
  577                     "cc");                                              \
  578         } else {                                                        \
  579                 __asm __volatile("                                      \
  580                         cld                                     ;       \
  581                         repne                                   ;       \
  582                         stosb"                                  :       \
  583                     "+D" (_port), "+c" (_cnt) : "a" ((v))       :       \
  584                     "memory", "cc");                                    \
  585         }                                                               \
  586 } while (0)
  587 
  588 #define bus_space_set_region_2(t, h, o, v, cnt) do {                    \
  589         int _port = (h)+(o); int _cnt = (cnt);                          \
  590         if ((t) == I386_BUS_SPACE_IO) {                                 \
  591                 __asm __volatile("                                      \
  592                 1:      outw %%ax,%w0                           ;       \
  593                         addl $2, %0                             ;       \
  594                         loop 1b"                                :       \
  595                     "+d" (_port), "+c" (_cnt) : "a" ((v))       :       \
  596                     "cc");                                              \
  597         } else {                                                        \
  598                 __asm __volatile("                                      \
  599                         cld                                     ;       \
  600                         repne                                   ;       \
  601                         stosw"                                  :       \
  602                     "+D" (_port), "+c" (_cnt) : "a" ((v))       :       \
  603                     "memory", "cc");                                    \
  604         }                                                               \
  605 } while (0)
  606 
  607 #define bus_space_set_region_4(t, h, o, v, cnt) do {                    \
  608         int _port = (h)+(o); int _cnt = (cnt);                          \
  609         if ((t) == I386_BUS_SPACE_IO) {                                 \
  610                 __asm __volatile("                                      \
  611                 1:      outl %%eax,%w0                          ;       \
  612                         addl $4, %0                             ;       \
  613                         loop 1b"                                :       \
  614                     "+d" (_port), "+c" (_cnt) : "a" ((v))       :       \
  615                     "cc");                                              \
  616         } else {                                                        \
  617                 __asm __volatile("                                      \
  618                         cld                                     ;       \
  619                         repne                                   ;       \
  620                         stosl"                                  :       \
  621                     "+D" (_port), "+c" (_cnt) : "a" ((v))       :       \
  622                     "memory", "cc");                                    \
  623         }                                                               \
  624 } while (0)
  625 
  626 #if 0   /* Cause a link error for bus_space_set_region_8 */
  627 #define bus_space_set_region_8                                  \
  628                         !!! bus_space_set_region_8 unimplemented !!!
  629 #endif
  630 
  631 /*
  632  *      void bus_space_copy_N(bus_space_tag_t tag,
  633  *          bus_space_handle_t bsh1, bus_size_t off1,
  634  *          bus_space_handle_t bsh2, bus_size_t off2,
  635  *          size_t count);
  636  *
  637  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
  638  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
  639  */
  640 
  641 #define bus_space_copy_1(t, h1, o1, h2, o2, cnt) do {                   \
  642         int _port1 = (h1)+(o1); int _port2 = (h2)+(o2); int _cnt=(cnt); \
  643         if ((t) == I386_BUS_SPACE_IO) {                                 \
  644                 __asm __volatile("                                      \
  645                 1:      movl %k1,%%edx                          ;       \
  646                         inb  %%dx,%%al                          ;       \
  647                         movl %k0,%%edx                          ;       \
  648                         outb %%al,%%dx                          ;       \
  649                         incl %0                                 ;       \
  650                         incl %1                                 ;       \
  651                         loop 1b"                                :       \
  652                     "+D" (_port2), "+S" (_port1), "+c" ((_cnt)) ::      \
  653                     "%edx", "%eax", "cc");                              \
  654         } else                                                          \
  655                 i386_space_copy(_port1, _port2, 1, _cnt);               \
  656 } while (0)
  657 
  658 #define bus_space_copy_2(t, h1, o1, h2, o2, cnt) do {                   \
  659         int _port1 = (h1)+(o1); int _port2 = (h2)+(o2); int _cnt=(cnt); \
  660         if ((t) == I386_BUS_SPACE_IO) {                                 \
  661                 __asm __volatile("                                      \
  662                 1:      movl %k1,%%edx                          ;       \
  663                         inw  %%dx,%%ax                          ;       \
  664                         movl %k0,%%edx                          ;       \
  665                         outw %%ax,%%dx                          ;       \
  666                         addl $2, %0                             ;       \
  667                         addl $2, %1                             ;       \
  668                         loop 1b"                                :       \
  669                     "+D" (_port2), "+ES" (_port1), "+c" ((_cnt))        ::      \
  670                     "%edx", "%eax", "cc");                              \
  671         } else                                                          \
  672                 i386_space_copy(_port1, _port2, 2, _cnt);               \
  673 } while (0)
  674 
  675 #define bus_space_copy_4(t, h1, o1, h2, o2, cnt) do {                   \
  676         int _port1 = (h1)+(o1); int _port2 = (h2)+(o2); int _cnt=(cnt); \
  677         if ((t) == I386_BUS_SPACE_IO) {                                 \
  678                 __asm __volatile("                                      \
  679                 1:      movl %k1,%%edx                          ;       \
  680                         inl  %%dx,%%eax                         ;       \
  681                         movl %k0,%%edx                          ;       \
  682                         outl %%eax,%%dx                         ;       \
  683                         addl $4, %0                             ;       \
  684                         addl $4, %1                             ;       \
  685                         loop 1b"                                :       \
  686                     "+D" (_port2), "+ES" (_port1), "+c" ((_cnt))        ::      \
  687                     "%edx", "%eax", "cc");                              \
  688         } else                                                          \
  689                 i386_space_copy(_port1, _port2, 4, _cnt);               \
  690 } while (0)
  691 
  692 #if 0   /* Cause a link error for bus_space_copy_8 */
  693 #define bus_space_copy_8                                        \
  694                         !!! bus_space_copy_8 unimplemented !!!
  695 #endif
  696 
  697 #define i386_space_copy1(a1, a2, cnt, movs, df)         \
  698         __asm __volatile(df "\n\trep\n\t" movs :        \
  699             "+S" (a1), "+D" (a2), "+c" (cnt)    :: "memory", "cc");
  700 
  701 #define i386_space_copy(a1, a2, sz, cnt) do {                           \
  702         if ((void *)(a1) < (void *)(a2)) {                              \
  703                 a1 += ((cnt) - 1) * (sz); a2 += ((cnt) - 1) * (sz);     \
  704                 switch (sz) {                                           \
  705                 case 1: i386_space_copy1(a1,a2,cnt,"movsb","std");break;\
  706                 case 2: i386_space_copy1(a1,a2,cnt,"movsw","std");break;\
  707                 case 4: i386_space_copy1(a1,a2,cnt,"movsl","std");break;\
  708                 }                                                       \
  709         } else                                                          \
  710                 switch (sz) {                                           \
  711                 case 1: i386_space_copy1(a1,a2,cnt,"movsb","cld");break;\
  712                 case 2: i386_space_copy1(a1,a2,cnt,"movsw","cld");break;\
  713                 case 4: i386_space_copy1(a1,a2,cnt,"movsl","cld");break;\
  714                 }                                                       \
  715 } while (0)
  716 
  717 /*
  718  * Bus read/write barrier methods.
  719  *
  720  *      void bus_space_barrier(bus_space_tag_t tag,
  721  *          bus_space_handle_t bsh, bus_size_t offset,
  722  *          bus_size_t len, int flags);
  723  *
  724  * Note: the i386 does not currently require barriers, but we must
  725  * provide the flags to MI code.
  726  */
  727 #define bus_space_barrier(t, h, o, l, f)        \
  728         ((void)((void)(t), (void)(h), (void)(o), (void)(l), (void)(f)))
  729 #define BUS_SPACE_BARRIER_READ  0x01            /* force read barrier */
  730 #define BUS_SPACE_BARRIER_WRITE 0x02            /* force write barrier */
  731 /* Compatibility defines */
  732 #define BUS_BARRIER_READ        BUS_SPACE_BARRIER_READ
  733 #define BUS_BARRIER_WRITE       BUS_SPACE_BARRIER_WRITE
  734 
  735 /*
  736  * Flags used in various bus DMA methods.
  737  */
  738 #define BUS_DMA_WAITOK          0x000   /* safe to sleep (pseudo-flag) */
  739 #define BUS_DMA_NOWAIT          0x001   /* not safe to sleep */
  740 #define BUS_DMA_ALLOCNOW        0x002   /* perform resource allocation now */
  741 #define BUS_DMA_COHERENT        0x004   /* hint: map memory DMA coherent */
  742 #define BUS_DMA_BUS1            0x010   /* placeholders for bus functions... */
  743 #define BUS_DMA_BUS2            0x020
  744 #define BUS_DMA_BUS3            0x040
  745 #define BUS_DMA_24BIT           0x080   /* isadma map */
  746 #define BUS_DMA_STREAMING       0x100   /* hint: sequential, unidirectional */
  747 #define BUS_DMA_READ            0x200   /* mapping is device -> memory only */
  748 #define BUS_DMA_WRITE           0x400   /* mapping is memory -> device only */
  749 
  750 /* Forwards needed by prototypes below. */
  751 struct mbuf;
  752 struct proc;
  753 struct uio;
  754 
  755 /*
  756  * Operations performed by bus_dmamap_sync().
  757  */
  758 #define BUS_DMASYNC_PREREAD     0x01
  759 #define BUS_DMASYNC_POSTREAD    0x02
  760 #define BUS_DMASYNC_PREWRITE    0x04
  761 #define BUS_DMASYNC_POSTWRITE   0x08
  762 
  763 typedef struct i386_bus_dma_tag         *bus_dma_tag_t;
  764 typedef struct i386_bus_dmamap          *bus_dmamap_t;
  765 
  766 /*
  767  *      bus_dma_segment_t
  768  *
  769  *      Describes a single contiguous DMA transaction.  Values
  770  *      are suitable for programming into DMA registers.
  771  */
  772 struct i386_bus_dma_segment {
  773         bus_addr_t      ds_addr;        /* DMA address */
  774         bus_size_t      ds_len;         /* length of transfer */
  775 };
  776 typedef struct i386_bus_dma_segment     bus_dma_segment_t;
  777 
  778 /*
  779  *      bus_dma_tag_t
  780  *
  781  *      A machine-dependent opaque type describing the implementation of
  782  *      DMA for a given bus.
  783  */
  784 
  785 struct i386_bus_dma_tag {
  786         void    *_cookie;               /* cookie used in the guts */
  787 
  788         /*
  789          * DMA mapping methods.
  790          */
  791         int     (*_dmamap_create)(bus_dma_tag_t, bus_size_t, int,
  792                     bus_size_t, bus_size_t, int, bus_dmamap_t *);
  793         void    (*_dmamap_destroy)(bus_dma_tag_t, bus_dmamap_t);
  794         int     (*_dmamap_load)(bus_dma_tag_t, bus_dmamap_t, void *,
  795                     bus_size_t, struct proc *, int);
  796         int     (*_dmamap_load_mbuf)(bus_dma_tag_t, bus_dmamap_t,
  797                     struct mbuf *, int);
  798         int     (*_dmamap_load_uio)(bus_dma_tag_t, bus_dmamap_t,
  799                     struct uio *, int);
  800         int     (*_dmamap_load_raw)(bus_dma_tag_t, bus_dmamap_t,
  801                     bus_dma_segment_t *, int, bus_size_t, int);
  802         void    (*_dmamap_unload)(bus_dma_tag_t, bus_dmamap_t);
  803         void    (*_dmamap_sync)(bus_dma_tag_t, bus_dmamap_t,
  804                     bus_addr_t, bus_size_t, int);
  805 
  806         /*
  807          * DMA memory utility functions.
  808          */
  809         int     (*_dmamem_alloc)(bus_dma_tag_t, bus_size_t, bus_size_t,
  810                     bus_size_t, bus_dma_segment_t *, int, int *, int);
  811         void    (*_dmamem_free)(bus_dma_tag_t,
  812                     bus_dma_segment_t *, int);
  813         int     (*_dmamem_map)(bus_dma_tag_t, bus_dma_segment_t *,
  814                     int, size_t, caddr_t *, int);
  815         void    (*_dmamem_unmap)(bus_dma_tag_t, caddr_t, size_t);
  816         paddr_t (*_dmamem_mmap)(bus_dma_tag_t, bus_dma_segment_t *,
  817                     int, off_t, int, int);
  818 };
  819 
  820 #define bus_dmamap_create(t, s, n, m, b, f, p)                  \
  821         (*(t)->_dmamap_create)((t), (s), (n), (m), (b), (f), (p))
  822 #define bus_dmamap_destroy(t, p)                                \
  823         (*(t)->_dmamap_destroy)((t), (p))
  824 #define bus_dmamap_load(t, m, b, s, p, f)                       \
  825         (*(t)->_dmamap_load)((t), (m), (b), (s), (p), (f))
  826 #define bus_dmamap_load_mbuf(t, m, b, f)                        \
  827         (*(t)->_dmamap_load_mbuf)((t), (m), (b), (f))
  828 #define bus_dmamap_load_uio(t, m, u, f)                         \
  829         (*(t)->_dmamap_load_uio)((t), (m), (u), (f))
  830 #define bus_dmamap_load_raw(t, m, sg, n, s, f)                  \
  831         (*(t)->_dmamap_load_raw)((t), (m), (sg), (n), (s), (f))
  832 #define bus_dmamap_unload(t, p)                                 \
  833         (*(t)->_dmamap_unload)((t), (p))
  834 #define bus_dmamap_sync(t, p, o, l, ops)                        \
  835         (void)((t)->_dmamap_sync ?                              \
  836             (*(t)->_dmamap_sync)((t), (p), (o), (l), (ops)) : (void)0)
  837 
  838 #define bus_dmamem_alloc(t, s, a, b, sg, n, r, f)               \
  839         (*(t)->_dmamem_alloc)((t), (s), (a), (b), (sg), (n), (r), (f))
  840 #define bus_dmamem_free(t, sg, n)                               \
  841         (*(t)->_dmamem_free)((t), (sg), (n))
  842 #define bus_dmamem_map(t, sg, n, s, k, f)                       \
  843         (*(t)->_dmamem_map)((t), (sg), (n), (s), (k), (f))
  844 #define bus_dmamem_unmap(t, k, s)                               \
  845         (*(t)->_dmamem_unmap)((t), (k), (s))
  846 #define bus_dmamem_mmap(t, sg, n, o, p, f)                      \
  847         (*(t)->_dmamem_mmap)((t), (sg), (n), (o), (p), (f))
  848 
  849 /*
  850  *      bus_dmamap_t
  851  *
  852  *      Describes a DMA mapping.
  853  */
  854 struct i386_bus_dmamap {
  855         /*
  856          * PRIVATE MEMBERS: not for use by machine-independent code.
  857          */
  858         bus_size_t      _dm_size;       /* largest DMA transfer mappable */
  859         int             _dm_segcnt;     /* number of segs this map can map */
  860         bus_size_t      _dm_maxsegsz;   /* largest possible segment */
  861         bus_size_t      _dm_boundary;   /* don't cross this */
  862         int             _dm_flags;      /* misc. flags */
  863 
  864         void            *_dm_cookie;    /* cookie for bus-specific functions */
  865 
  866         /*
  867          * PUBLIC MEMBERS: these are used by machine-independent code.
  868          */
  869         bus_size_t      dm_mapsize;     /* size of the mapping */
  870         int             dm_nsegs;       /* # valid segments in mapping */
  871         bus_dma_segment_t dm_segs[1];   /* segments; variable length */
  872 };
  873 
  874 #ifdef _I386_BUS_DMA_PRIVATE
  875 int     _bus_dmamap_create(bus_dma_tag_t, bus_size_t, int, bus_size_t,
  876             bus_size_t, int, bus_dmamap_t *);
  877 void    _bus_dmamap_destroy(bus_dma_tag_t, bus_dmamap_t);
  878 int     _bus_dmamap_load(bus_dma_tag_t, bus_dmamap_t, void *,
  879             bus_size_t, struct proc *, int);
  880 int     _bus_dmamap_load_mbuf(bus_dma_tag_t, bus_dmamap_t,
  881             struct mbuf *, int);
  882 int     _bus_dmamap_load_uio(bus_dma_tag_t, bus_dmamap_t,
  883             struct uio *, int);
  884 int     _bus_dmamap_load_raw(bus_dma_tag_t, bus_dmamap_t,
  885             bus_dma_segment_t *, int, bus_size_t, int);
  886 void    _bus_dmamap_unload(bus_dma_tag_t, bus_dmamap_t);
  887 void    _bus_dmamap_sync(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
  888             bus_size_t, int);
  889 
  890 int     _bus_dmamem_alloc(bus_dma_tag_t tag, bus_size_t size,
  891             bus_size_t alignment, bus_size_t boundary,
  892             bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
  893 void    _bus_dmamem_free(bus_dma_tag_t tag, bus_dma_segment_t *segs,
  894             int nsegs);
  895 int     _bus_dmamem_map(bus_dma_tag_t tag, bus_dma_segment_t *segs,
  896             int nsegs, size_t size, caddr_t *kvap, int flags);
  897 void    _bus_dmamem_unmap(bus_dma_tag_t tag, caddr_t kva,
  898             size_t size);
  899 paddr_t _bus_dmamem_mmap(bus_dma_tag_t tag, bus_dma_segment_t *segs,
  900             int nsegs, off_t off, int prot, int flags);
  901 
  902 int     _bus_dmamem_alloc_range(bus_dma_tag_t tag, bus_size_t size,
  903             bus_size_t alignment, bus_size_t boundary,
  904             bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags,
  905             paddr_t low, paddr_t high);
  906 #endif /* _I386_BUS_DMA_PRIVATE */
  907 
  908 #endif /* _I386_BUS_H_ */

/* [<][>][^][v][top][bottom][index][help] */