]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - sys/x86/include/bus.h
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / sys / x86 / include / bus.h
1 /*-
2  * Copyright (c) KATO Takenori, 1999.
3  *
4  * All rights reserved.  Unpublished rights reserved under the copyright
5  * laws of Japan.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer as
13  *    the first lines of this file unmodified.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  * 
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $FreeBSD$
32  */
33
34 /*      $NetBSD: bus.h,v 1.12 1997/10/01 08:25:15 fvdl Exp $    */
35
36 /*-
37  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
38  * All rights reserved.
39  *
40  * This code is derived from software contributed to The NetBSD Foundation
41  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
42  * NASA Ames Research Center.
43  *
44  * Redistribution and use in source and binary forms, with or without
45  * modification, are permitted provided that the following conditions
46  * are met:
47  * 1. Redistributions of source code must retain the above copyright
48  *    notice, this list of conditions and the following disclaimer.
49  * 2. Redistributions in binary form must reproduce the above copyright
50  *    notice, this list of conditions and the following disclaimer in the
51  *    documentation and/or other materials provided with the distribution.
52  * 3. All advertising materials mentioning features or use of this software
53  *    must display the following acknowledgement:
54  *      This product includes software developed by the NetBSD
55  *      Foundation, Inc. and its contributors.
56  * 4. Neither the name of The NetBSD Foundation nor the names of its
57  *    contributors may be used to endorse or promote products derived
58  *    from this software without specific prior written permission.
59  *
60  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
61  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
62  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
63  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
64  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
65  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
66  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
67  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
68  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
69  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
70  * POSSIBILITY OF SUCH DAMAGE.
71  */
72
73 /*-
74  * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
75  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
76  *
77  * Redistribution and use in source and binary forms, with or without
78  * modification, are permitted provided that the following conditions
79  * are met:
80  * 1. Redistributions of source code must retain the above copyright
81  *    notice, this list of conditions and the following disclaimer.
82  * 2. Redistributions in binary form must reproduce the above copyright
83  *    notice, this list of conditions and the following disclaimer in the
84  *    documentation and/or other materials provided with the distribution.
85  * 3. All advertising materials mentioning features or use of this software
86  *    must display the following acknowledgement:
87  *      This product includes software developed by Christopher G. Demetriou
88  *      for the NetBSD Project.
89  * 4. The name of the author may not be used to endorse or promote products
90  *    derived from this software without specific prior written permission
91  *
92  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
93  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
94  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
95  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
96  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
97  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
98  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
99  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
100  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
101  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
102  */
103
104 #ifndef _X86_BUS_H_
105 #define _X86_BUS_H_
106
107 #include <machine/_bus.h>
108 #include <machine/cpufunc.h>
109
110 #ifndef __GNUCLIKE_ASM
111 # ifndef lint
112 #  error "no assembler code for your compiler"
113 # endif
114 #endif
115
116 /*
117  * Values for the x86 bus space tag, not to be used directly by MI code.
118  */
119 #define X86_BUS_SPACE_IO        0       /* space is i/o space */
120 #define X86_BUS_SPACE_MEM       1       /* space is mem space */
121
122 #define BUS_SPACE_MAXSIZE_24BIT 0xFFFFFF
123 #define BUS_SPACE_MAXSIZE_32BIT 0xFFFFFFFF
124 #define BUS_SPACE_MAXSIZE       0xFFFFFFFF
125 #define BUS_SPACE_MAXADDR_24BIT 0xFFFFFF
126 #define BUS_SPACE_MAXADDR_32BIT 0xFFFFFFFF
127 #if defined(__amd64__) || defined(PAE)
128 #define BUS_SPACE_MAXADDR       0xFFFFFFFFFFFFFFFFULL
129 #else
130 #define BUS_SPACE_MAXADDR       0xFFFFFFFF
131 #endif
132
133 #define BUS_SPACE_UNRESTRICTED  (~0)
134
135 /*
136  * Map a region of device bus space into CPU virtual address space.
137  */
138
139 static __inline int bus_space_map(bus_space_tag_t t, bus_addr_t addr,
140                                   bus_size_t size, int flags,
141                                   bus_space_handle_t *bshp);
142
143 static __inline int
144 bus_space_map(bus_space_tag_t t __unused, bus_addr_t addr,
145               bus_size_t size __unused, int flags __unused,
146               bus_space_handle_t *bshp)
147 {
148
149         *bshp = addr;
150         return (0);
151 }
152
153 /*
154  * Unmap a region of device bus space.
155  */
156
157 static __inline void bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh,
158                                      bus_size_t size);
159
160 static __inline void
161 bus_space_unmap(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
162                 bus_size_t size __unused)
163 {
164 }
165
166 /*
167  * Get a new handle for a subregion of an already-mapped area of bus space.
168  */
169
170 static __inline int bus_space_subregion(bus_space_tag_t t,
171                                         bus_space_handle_t bsh,
172                                         bus_size_t offset, bus_size_t size,
173                                         bus_space_handle_t *nbshp);
174
175 static __inline int
176 bus_space_subregion(bus_space_tag_t t __unused, bus_space_handle_t bsh,
177                     bus_size_t offset, bus_size_t size __unused,
178                     bus_space_handle_t *nbshp)
179 {
180
181         *nbshp = bsh + offset;
182         return (0);
183 }
184
185 /*
186  * Allocate a region of memory that is accessible to devices in bus space.
187  */
188
189 int     bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart,
190                         bus_addr_t rend, bus_size_t size, bus_size_t align,
191                         bus_size_t boundary, int flags, bus_addr_t *addrp,
192                         bus_space_handle_t *bshp);
193
194 /*
195  * Free a region of bus space accessible memory.
196  */
197
198 static __inline void bus_space_free(bus_space_tag_t t, bus_space_handle_t bsh,
199                                     bus_size_t size);
200
201 static __inline void
202 bus_space_free(bus_space_tag_t t __unused, bus_space_handle_t bsh __unused,
203                bus_size_t size __unused)
204 {
205 }
206
207
208 /*
209  * Read a 1, 2, 4, or 8 byte quantity from bus space
210  * described by tag/handle/offset.
211  */
212 static __inline u_int8_t bus_space_read_1(bus_space_tag_t tag,
213                                           bus_space_handle_t handle,
214                                           bus_size_t offset);
215
216 static __inline u_int16_t bus_space_read_2(bus_space_tag_t tag,
217                                            bus_space_handle_t handle,
218                                            bus_size_t offset);
219
220 static __inline u_int32_t bus_space_read_4(bus_space_tag_t tag,
221                                            bus_space_handle_t handle,
222                                            bus_size_t offset);
223
224 static __inline u_int8_t
225 bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t handle,
226                  bus_size_t offset)
227 {
228
229         if (tag == X86_BUS_SPACE_IO)
230                 return (inb(handle + offset));
231         return (*(volatile u_int8_t *)(handle + offset));
232 }
233
234 static __inline u_int16_t
235 bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t handle,
236                  bus_size_t offset)
237 {
238
239         if (tag == X86_BUS_SPACE_IO)
240                 return (inw(handle + offset));
241         return (*(volatile u_int16_t *)(handle + offset));
242 }
243
244 static __inline u_int32_t
245 bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t handle,
246                  bus_size_t offset)
247 {
248
249         if (tag == X86_BUS_SPACE_IO)
250                 return (inl(handle + offset));
251         return (*(volatile u_int32_t *)(handle + offset));
252 }
253
254 #if 0   /* Cause a link error for bus_space_read_8 */
255 #define bus_space_read_8(t, h, o)       !!! bus_space_read_8 unimplemented !!!
256 #endif
257
258 /*
259  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
260  * described by tag/handle/offset and copy into buffer provided.
261  */
262 static __inline void bus_space_read_multi_1(bus_space_tag_t tag,
263                                             bus_space_handle_t bsh,
264                                             bus_size_t offset, u_int8_t *addr,
265                                             size_t count);
266
267 static __inline void bus_space_read_multi_2(bus_space_tag_t tag,
268                                             bus_space_handle_t bsh,
269                                             bus_size_t offset, u_int16_t *addr,
270                                             size_t count);
271
272 static __inline void bus_space_read_multi_4(bus_space_tag_t tag,
273                                             bus_space_handle_t bsh,
274                                             bus_size_t offset, u_int32_t *addr,
275                                             size_t count);
276
277 static __inline void
278 bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
279                        bus_size_t offset, u_int8_t *addr, size_t count)
280 {
281
282         if (tag == X86_BUS_SPACE_IO)
283                 insb(bsh + offset, addr, count);
284         else {
285 #ifdef __GNUCLIKE_ASM
286                 __asm __volatile("                              \n\
287                         cld                                     \n\
288                 1:      movb (%2),%%al                          \n\
289                         stosb                                   \n\
290                         loop 1b"                                :
291                     "=D" (addr), "=c" (count)                   :
292                     "r" (bsh + offset), "0" (addr), "1" (count) :
293                     "%eax", "memory");
294 #endif
295         }
296 }
297
298 static __inline void
299 bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
300                        bus_size_t offset, u_int16_t *addr, size_t count)
301 {
302
303         if (tag == X86_BUS_SPACE_IO)
304                 insw(bsh + offset, addr, count);
305         else {
306 #ifdef __GNUCLIKE_ASM
307                 __asm __volatile("                              \n\
308                         cld                                     \n\
309                 1:      movw (%2),%%ax                          \n\
310                         stosw                                   \n\
311                         loop 1b"                                :
312                     "=D" (addr), "=c" (count)                   :
313                     "r" (bsh + offset), "0" (addr), "1" (count) :
314                     "%eax", "memory");
315 #endif
316         }
317 }
318
319 static __inline void
320 bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
321                        bus_size_t offset, u_int32_t *addr, size_t count)
322 {
323
324         if (tag == X86_BUS_SPACE_IO)
325                 insl(bsh + offset, addr, count);
326         else {
327 #ifdef __GNUCLIKE_ASM
328                 __asm __volatile("                              \n\
329                         cld                                     \n\
330                 1:      movl (%2),%%eax                         \n\
331                         stosl                                   \n\
332                         loop 1b"                                :
333                     "=D" (addr), "=c" (count)                   :
334                     "r" (bsh + offset), "0" (addr), "1" (count) :
335                     "%eax", "memory");
336 #endif
337         }
338 }
339
340 #if 0   /* Cause a link error for bus_space_read_multi_8 */
341 #define bus_space_read_multi_8  !!! bus_space_read_multi_8 unimplemented !!!
342 #endif
343
344 /*
345  * Read `count' 1, 2, 4, or 8 byte quantities from bus space
346  * described by tag/handle and starting at `offset' and copy into
347  * buffer provided.
348  */
349 static __inline void bus_space_read_region_1(bus_space_tag_t tag,
350                                              bus_space_handle_t bsh,
351                                              bus_size_t offset, u_int8_t *addr,
352                                              size_t count);
353
354 static __inline void bus_space_read_region_2(bus_space_tag_t tag,
355                                              bus_space_handle_t bsh,
356                                              bus_size_t offset, u_int16_t *addr,
357                                              size_t count);
358
359 static __inline void bus_space_read_region_4(bus_space_tag_t tag,
360                                              bus_space_handle_t bsh,
361                                              bus_size_t offset, u_int32_t *addr,
362                                              size_t count);
363
364
365 static __inline void
366 bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
367                         bus_size_t offset, u_int8_t *addr, size_t count)
368 {
369
370         if (tag == X86_BUS_SPACE_IO) {
371                 int _port_ = bsh + offset;
372 #ifdef __GNUCLIKE_ASM
373                 __asm __volatile("                              \n\
374                         cld                                     \n\
375                 1:      inb %w2,%%al                            \n\
376                         stosb                                   \n\
377                         incl %2                                 \n\
378                         loop 1b"                                :
379                     "=D" (addr), "=c" (count), "=d" (_port_)    :
380                     "0" (addr), "1" (count), "2" (_port_)       :
381                     "%eax", "memory", "cc");
382 #endif
383         } else {
384                 bus_space_handle_t _port_ = bsh + offset;
385 #ifdef __GNUCLIKE_ASM
386                 __asm __volatile("                              \n\
387                         cld                                     \n\
388                         repne                                   \n\
389                         movsb"                                  :
390                     "=D" (addr), "=c" (count), "=S" (_port_)    :
391                     "0" (addr), "1" (count), "2" (_port_)       :
392                     "memory", "cc");
393 #endif
394         }
395 }
396
397 static __inline void
398 bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
399                         bus_size_t offset, u_int16_t *addr, size_t count)
400 {
401
402         if (tag == X86_BUS_SPACE_IO) {
403                 int _port_ = bsh + offset;
404 #ifdef __GNUCLIKE_ASM
405                 __asm __volatile("                              \n\
406                         cld                                     \n\
407                 1:      inw %w2,%%ax                            \n\
408                         stosw                                   \n\
409                         addl $2,%2                              \n\
410                         loop 1b"                                :
411                     "=D" (addr), "=c" (count), "=d" (_port_)    :
412                     "0" (addr), "1" (count), "2" (_port_)       :
413                     "%eax", "memory", "cc");
414 #endif
415         } else {
416                 bus_space_handle_t _port_ = bsh + offset;
417 #ifdef __GNUCLIKE_ASM
418                 __asm __volatile("                              \n\
419                         cld                                     \n\
420                         repne                                   \n\
421                         movsw"                                  :
422                     "=D" (addr), "=c" (count), "=S" (_port_)    :
423                     "0" (addr), "1" (count), "2" (_port_)       :
424                     "memory", "cc");
425 #endif
426         }
427 }
428
429 static __inline void
430 bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
431                         bus_size_t offset, u_int32_t *addr, size_t count)
432 {
433
434         if (tag == X86_BUS_SPACE_IO) {
435                 int _port_ = bsh + offset;
436 #ifdef __GNUCLIKE_ASM
437                 __asm __volatile("                              \n\
438                         cld                                     \n\
439                 1:      inl %w2,%%eax                           \n\
440                         stosl                                   \n\
441                         addl $4,%2                              \n\
442                         loop 1b"                                :
443                     "=D" (addr), "=c" (count), "=d" (_port_)    :
444                     "0" (addr), "1" (count), "2" (_port_)       :
445                     "%eax", "memory", "cc");
446 #endif
447         } else {
448                 bus_space_handle_t _port_ = bsh + offset;
449 #ifdef __GNUCLIKE_ASM
450                 __asm __volatile("                              \n\
451                         cld                                     \n\
452                         repne                                   \n\
453                         movsl"                                  :
454                     "=D" (addr), "=c" (count), "=S" (_port_)    :
455                     "0" (addr), "1" (count), "2" (_port_)       :
456                     "memory", "cc");
457 #endif
458         }
459 }
460
461 #if 0   /* Cause a link error for bus_space_read_region_8 */
462 #define bus_space_read_region_8 !!! bus_space_read_region_8 unimplemented !!!
463 #endif
464
465 /*
466  * Write the 1, 2, 4, or 8 byte value `value' to bus space
467  * described by tag/handle/offset.
468  */
469
470 static __inline void bus_space_write_1(bus_space_tag_t tag,
471                                        bus_space_handle_t bsh,
472                                        bus_size_t offset, u_int8_t value);
473
474 static __inline void bus_space_write_2(bus_space_tag_t tag,
475                                        bus_space_handle_t bsh,
476                                        bus_size_t offset, u_int16_t value);
477
478 static __inline void bus_space_write_4(bus_space_tag_t tag,
479                                        bus_space_handle_t bsh,
480                                        bus_size_t offset, u_int32_t value);
481
482 static __inline void
483 bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
484                        bus_size_t offset, u_int8_t value)
485 {
486
487         if (tag == X86_BUS_SPACE_IO)
488                 outb(bsh + offset, value);
489         else
490                 *(volatile u_int8_t *)(bsh + offset) = value;
491 }
492
493 static __inline void
494 bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
495                        bus_size_t offset, u_int16_t value)
496 {
497
498         if (tag == X86_BUS_SPACE_IO)
499                 outw(bsh + offset, value);
500         else
501                 *(volatile u_int16_t *)(bsh + offset) = value;
502 }
503
504 static __inline void
505 bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
506                        bus_size_t offset, u_int32_t value)
507 {
508
509         if (tag == X86_BUS_SPACE_IO)
510                 outl(bsh + offset, value);
511         else
512                 *(volatile u_int32_t *)(bsh + offset) = value;
513 }
514
515 #if 0   /* Cause a link error for bus_space_write_8 */
516 #define bus_space_write_8       !!! bus_space_write_8 not implemented !!!
517 #endif
518
519 /*
520  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer
521  * provided to bus space described by tag/handle/offset.
522  */
523
524 static __inline void bus_space_write_multi_1(bus_space_tag_t tag,
525                                              bus_space_handle_t bsh,
526                                              bus_size_t offset,
527                                              const u_int8_t *addr,
528                                              size_t count);
529 static __inline void bus_space_write_multi_2(bus_space_tag_t tag,
530                                              bus_space_handle_t bsh,
531                                              bus_size_t offset,
532                                              const u_int16_t *addr,
533                                              size_t count);
534
535 static __inline void bus_space_write_multi_4(bus_space_tag_t tag,
536                                              bus_space_handle_t bsh,
537                                              bus_size_t offset,
538                                              const u_int32_t *addr,
539                                              size_t count);
540
541 static __inline void
542 bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
543                         bus_size_t offset, const u_int8_t *addr, size_t count)
544 {
545
546         if (tag == X86_BUS_SPACE_IO)
547                 outsb(bsh + offset, addr, count);
548         else {
549 #ifdef __GNUCLIKE_ASM
550                 __asm __volatile("                              \n\
551                         cld                                     \n\
552                 1:      lodsb                                   \n\
553                         movb %%al,(%2)                          \n\
554                         loop 1b"                                :
555                     "=S" (addr), "=c" (count)                   :
556                     "r" (bsh + offset), "0" (addr), "1" (count) :
557                     "%eax", "memory", "cc");
558 #endif
559         }
560 }
561
562 static __inline void
563 bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
564                         bus_size_t offset, const u_int16_t *addr, size_t count)
565 {
566
567         if (tag == X86_BUS_SPACE_IO)
568                 outsw(bsh + offset, addr, count);
569         else {
570 #ifdef __GNUCLIKE_ASM
571                 __asm __volatile("                              \n\
572                         cld                                     \n\
573                 1:      lodsw                                   \n\
574                         movw %%ax,(%2)                          \n\
575                         loop 1b"                                :
576                     "=S" (addr), "=c" (count)                   :
577                     "r" (bsh + offset), "0" (addr), "1" (count) :
578                     "%eax", "memory", "cc");
579 #endif
580         }
581 }
582
583 static __inline void
584 bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
585                         bus_size_t offset, const u_int32_t *addr, size_t count)
586 {
587
588         if (tag == X86_BUS_SPACE_IO)
589                 outsl(bsh + offset, addr, count);
590         else {
591 #ifdef __GNUCLIKE_ASM
592                 __asm __volatile("                              \n\
593                         cld                                     \n\
594                 1:      lodsl                                   \n\
595                         movl %%eax,(%2)                         \n\
596                         loop 1b"                                :
597                     "=S" (addr), "=c" (count)                   :
598                     "r" (bsh + offset), "0" (addr), "1" (count) :
599                     "%eax", "memory", "cc");
600 #endif
601         }
602 }
603
604 #if 0   /* Cause a link error for bus_space_write_multi_8 */
605 #define bus_space_write_multi_8(t, h, o, a, c)                          \
606                         !!! bus_space_write_multi_8 unimplemented !!!
607 #endif
608
609 /*
610  * Write `count' 1, 2, 4, or 8 byte quantities from the buffer provided
611  * to bus space described by tag/handle starting at `offset'.
612  */
613
614 static __inline void bus_space_write_region_1(bus_space_tag_t tag,
615                                               bus_space_handle_t bsh,
616                                               bus_size_t offset,
617                                               const u_int8_t *addr,
618                                               size_t count);
619 static __inline void bus_space_write_region_2(bus_space_tag_t tag,
620                                               bus_space_handle_t bsh,
621                                               bus_size_t offset,
622                                               const u_int16_t *addr,
623                                               size_t count);
624 static __inline void bus_space_write_region_4(bus_space_tag_t tag,
625                                               bus_space_handle_t bsh,
626                                               bus_size_t offset,
627                                               const u_int32_t *addr,
628                                               size_t count);
629
630 static __inline void
631 bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
632                          bus_size_t offset, const u_int8_t *addr, size_t count)
633 {
634
635         if (tag == X86_BUS_SPACE_IO) {
636                 int _port_ = bsh + offset;
637 #ifdef __GNUCLIKE_ASM
638                 __asm __volatile("                              \n\
639                         cld                                     \n\
640                 1:      lodsb                                   \n\
641                         outb %%al,%w0                           \n\
642                         incl %0                                 \n\
643                         loop 1b"                                :
644                     "=d" (_port_), "=S" (addr), "=c" (count)    :
645                     "0" (_port_), "1" (addr), "2" (count)       :
646                     "%eax", "memory", "cc");
647 #endif
648         } else {
649                 bus_space_handle_t _port_ = bsh + offset;
650 #ifdef __GNUCLIKE_ASM
651                 __asm __volatile("                              \n\
652                         cld                                     \n\
653                         repne                                   \n\
654                         movsb"                                  :
655                     "=D" (_port_), "=S" (addr), "=c" (count)    :
656                     "0" (_port_), "1" (addr), "2" (count)       :
657                     "memory", "cc");
658 #endif
659         }
660 }
661
662 static __inline void
663 bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
664                          bus_size_t offset, const u_int16_t *addr, size_t count)
665 {
666
667         if (tag == X86_BUS_SPACE_IO) {
668                 int _port_ = bsh + offset;
669 #ifdef __GNUCLIKE_ASM
670                 __asm __volatile("                              \n\
671                         cld                                     \n\
672                 1:      lodsw                                   \n\
673                         outw %%ax,%w0                           \n\
674                         addl $2,%0                              \n\
675                         loop 1b"                                :
676                     "=d" (_port_), "=S" (addr), "=c" (count)    :
677                     "0" (_port_), "1" (addr), "2" (count)       :
678                     "%eax", "memory", "cc");
679 #endif
680         } else {
681                 bus_space_handle_t _port_ = bsh + offset;
682 #ifdef __GNUCLIKE_ASM
683                 __asm __volatile("                              \n\
684                         cld                                     \n\
685                         repne                                   \n\
686                         movsw"                                  :
687                     "=D" (_port_), "=S" (addr), "=c" (count)    :
688                     "0" (_port_), "1" (addr), "2" (count)       :
689                     "memory", "cc");
690 #endif
691         }
692 }
693
694 static __inline void
695 bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
696                          bus_size_t offset, const u_int32_t *addr, size_t count)
697 {
698
699         if (tag == X86_BUS_SPACE_IO) {
700                 int _port_ = bsh + offset;
701 #ifdef __GNUCLIKE_ASM
702                 __asm __volatile("                              \n\
703                         cld                                     \n\
704                 1:      lodsl                                   \n\
705                         outl %%eax,%w0                          \n\
706                         addl $4,%0                              \n\
707                         loop 1b"                                :
708                     "=d" (_port_), "=S" (addr), "=c" (count)    :
709                     "0" (_port_), "1" (addr), "2" (count)       :
710                     "%eax", "memory", "cc");
711 #endif
712         } else {
713                 bus_space_handle_t _port_ = bsh + offset;
714 #ifdef __GNUCLIKE_ASM
715                 __asm __volatile("                              \n\
716                         cld                                     \n\
717                         repne                                   \n\
718                         movsl"                                  :
719                     "=D" (_port_), "=S" (addr), "=c" (count)    :
720                     "0" (_port_), "1" (addr), "2" (count)       :
721                     "memory", "cc");
722 #endif
723         }
724 }
725
726 #if 0   /* Cause a link error for bus_space_write_region_8 */
727 #define bus_space_write_region_8                                        \
728                         !!! bus_space_write_region_8 unimplemented !!!
729 #endif
730
731 /*
732  * Write the 1, 2, 4, or 8 byte value `val' to bus space described
733  * by tag/handle/offset `count' times.
734  */
735
736 static __inline void bus_space_set_multi_1(bus_space_tag_t tag,
737                                            bus_space_handle_t bsh,
738                                            bus_size_t offset,
739                                            u_int8_t value, size_t count);
740 static __inline void bus_space_set_multi_2(bus_space_tag_t tag,
741                                            bus_space_handle_t bsh,
742                                            bus_size_t offset,
743                                            u_int16_t value, size_t count);
744 static __inline void bus_space_set_multi_4(bus_space_tag_t tag,
745                                            bus_space_handle_t bsh,
746                                            bus_size_t offset,
747                                            u_int32_t value, size_t count);
748
749 static __inline void
750 bus_space_set_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
751                       bus_size_t offset, u_int8_t value, size_t count)
752 {
753         bus_space_handle_t addr = bsh + offset;
754
755         if (tag == X86_BUS_SPACE_IO)
756                 while (count--)
757                         outb(addr, value);
758         else
759                 while (count--)
760                         *(volatile u_int8_t *)(addr) = value;
761 }
762
763 static __inline void
764 bus_space_set_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
765                      bus_size_t offset, u_int16_t value, size_t count)
766 {
767         bus_space_handle_t addr = bsh + offset;
768
769         if (tag == X86_BUS_SPACE_IO)
770                 while (count--)
771                         outw(addr, value);
772         else
773                 while (count--)
774                         *(volatile u_int16_t *)(addr) = value;
775 }
776
777 static __inline void
778 bus_space_set_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
779                       bus_size_t offset, u_int32_t value, size_t count)
780 {
781         bus_space_handle_t addr = bsh + offset;
782
783         if (tag == X86_BUS_SPACE_IO)
784                 while (count--)
785                         outl(addr, value);
786         else
787                 while (count--)
788                         *(volatile u_int32_t *)(addr) = value;
789 }
790
791 #if 0   /* Cause a link error for bus_space_set_multi_8 */
792 #define bus_space_set_multi_8 !!! bus_space_set_multi_8 unimplemented !!!
793 #endif
794
795 /*
796  * Write `count' 1, 2, 4, or 8 byte value `val' to bus space described
797  * by tag/handle starting at `offset'.
798  */
799
800 static __inline void bus_space_set_region_1(bus_space_tag_t tag,
801                                             bus_space_handle_t bsh,
802                                             bus_size_t offset, u_int8_t value,
803                                             size_t count);
804 static __inline void bus_space_set_region_2(bus_space_tag_t tag,
805                                             bus_space_handle_t bsh,
806                                             bus_size_t offset, u_int16_t value,
807                                             size_t count);
808 static __inline void bus_space_set_region_4(bus_space_tag_t tag,
809                                             bus_space_handle_t bsh,
810                                             bus_size_t offset, u_int32_t value,
811                                             size_t count);
812
813 static __inline void
814 bus_space_set_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
815                        bus_size_t offset, u_int8_t value, size_t count)
816 {
817         bus_space_handle_t addr = bsh + offset;
818
819         if (tag == X86_BUS_SPACE_IO)
820                 for (; count != 0; count--, addr++)
821                         outb(addr, value);
822         else
823                 for (; count != 0; count--, addr++)
824                         *(volatile u_int8_t *)(addr) = value;
825 }
826
827 static __inline void
828 bus_space_set_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
829                        bus_size_t offset, u_int16_t value, size_t count)
830 {
831         bus_space_handle_t addr = bsh + offset;
832
833         if (tag == X86_BUS_SPACE_IO)
834                 for (; count != 0; count--, addr += 2)
835                         outw(addr, value);
836         else
837                 for (; count != 0; count--, addr += 2)
838                         *(volatile u_int16_t *)(addr) = value;
839 }
840
841 static __inline void
842 bus_space_set_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
843                        bus_size_t offset, u_int32_t value, size_t count)
844 {
845         bus_space_handle_t addr = bsh + offset;
846
847         if (tag == X86_BUS_SPACE_IO)
848                 for (; count != 0; count--, addr += 4)
849                         outl(addr, value);
850         else
851                 for (; count != 0; count--, addr += 4)
852                         *(volatile u_int32_t *)(addr) = value;
853 }
854
855 #if 0   /* Cause a link error for bus_space_set_region_8 */
856 #define bus_space_set_region_8  !!! bus_space_set_region_8 unimplemented !!!
857 #endif
858
859 /*
860  * Copy `count' 1, 2, 4, or 8 byte values from bus space starting
861  * at tag/bsh1/off1 to bus space starting at tag/bsh2/off2.
862  */
863
864 static __inline void bus_space_copy_region_1(bus_space_tag_t tag,
865                                              bus_space_handle_t bsh1,
866                                              bus_size_t off1,
867                                              bus_space_handle_t bsh2,
868                                              bus_size_t off2, size_t count);
869
870 static __inline void bus_space_copy_region_2(bus_space_tag_t tag,
871                                              bus_space_handle_t bsh1,
872                                              bus_size_t off1,
873                                              bus_space_handle_t bsh2,
874                                              bus_size_t off2, size_t count);
875
876 static __inline void bus_space_copy_region_4(bus_space_tag_t tag,
877                                              bus_space_handle_t bsh1,
878                                              bus_size_t off1,
879                                              bus_space_handle_t bsh2,
880                                              bus_size_t off2, size_t count);
881
882 static __inline void
883 bus_space_copy_region_1(bus_space_tag_t tag, bus_space_handle_t bsh1,
884                         bus_size_t off1, bus_space_handle_t bsh2,
885                         bus_size_t off2, size_t count)
886 {
887         bus_space_handle_t addr1 = bsh1 + off1;
888         bus_space_handle_t addr2 = bsh2 + off2;
889
890         if (tag == X86_BUS_SPACE_IO) {
891                 if (addr1 >= addr2) {
892                         /* src after dest: copy forward */
893                         for (; count != 0; count--, addr1++, addr2++)
894                                 outb(addr2, inb(addr1));
895                 } else {
896                         /* dest after src: copy backwards */
897                         for (addr1 += (count - 1), addr2 += (count - 1);
898                             count != 0; count--, addr1--, addr2--)
899                                 outb(addr2, inb(addr1));
900                 }
901         } else {
902                 if (addr1 >= addr2) {
903                         /* src after dest: copy forward */
904                         for (; count != 0; count--, addr1++, addr2++)
905                                 *(volatile u_int8_t *)(addr2) =
906                                     *(volatile u_int8_t *)(addr1);
907                 } else {
908                         /* dest after src: copy backwards */
909                         for (addr1 += (count - 1), addr2 += (count - 1);
910                             count != 0; count--, addr1--, addr2--)
911                                 *(volatile u_int8_t *)(addr2) =
912                                     *(volatile u_int8_t *)(addr1);
913                 }
914         }
915 }
916
917 static __inline void
918 bus_space_copy_region_2(bus_space_tag_t tag, bus_space_handle_t bsh1,
919                         bus_size_t off1, bus_space_handle_t bsh2,
920                         bus_size_t off2, size_t count)
921 {
922         bus_space_handle_t addr1 = bsh1 + off1;
923         bus_space_handle_t addr2 = bsh2 + off2;
924
925         if (tag == X86_BUS_SPACE_IO) {
926                 if (addr1 >= addr2) {
927                         /* src after dest: copy forward */
928                         for (; count != 0; count--, addr1 += 2, addr2 += 2)
929                                 outw(addr2, inw(addr1));
930                 } else {
931                         /* dest after src: copy backwards */
932                         for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
933                             count != 0; count--, addr1 -= 2, addr2 -= 2)
934                                 outw(addr2, inw(addr1));
935                 }
936         } else {
937                 if (addr1 >= addr2) {
938                         /* src after dest: copy forward */
939                         for (; count != 0; count--, addr1 += 2, addr2 += 2)
940                                 *(volatile u_int16_t *)(addr2) =
941                                     *(volatile u_int16_t *)(addr1);
942                 } else {
943                         /* dest after src: copy backwards */
944                         for (addr1 += 2 * (count - 1), addr2 += 2 * (count - 1);
945                             count != 0; count--, addr1 -= 2, addr2 -= 2)
946                                 *(volatile u_int16_t *)(addr2) =
947                                     *(volatile u_int16_t *)(addr1);
948                 }
949         }
950 }
951
952 static __inline void
953 bus_space_copy_region_4(bus_space_tag_t tag, bus_space_handle_t bsh1,
954                         bus_size_t off1, bus_space_handle_t bsh2,
955                         bus_size_t off2, size_t count)
956 {
957         bus_space_handle_t addr1 = bsh1 + off1;
958         bus_space_handle_t addr2 = bsh2 + off2;
959
960         if (tag == X86_BUS_SPACE_IO) {
961                 if (addr1 >= addr2) {
962                         /* src after dest: copy forward */
963                         for (; count != 0; count--, addr1 += 4, addr2 += 4)
964                                 outl(addr2, inl(addr1));
965                 } else {
966                         /* dest after src: copy backwards */
967                         for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
968                             count != 0; count--, addr1 -= 4, addr2 -= 4)
969                                 outl(addr2, inl(addr1));
970                 }
971         } else {
972                 if (addr1 >= addr2) {
973                         /* src after dest: copy forward */
974                         for (; count != 0; count--, addr1 += 4, addr2 += 4)
975                                 *(volatile u_int32_t *)(addr2) =
976                                     *(volatile u_int32_t *)(addr1);
977                 } else {
978                         /* dest after src: copy backwards */
979                         for (addr1 += 4 * (count - 1), addr2 += 4 * (count - 1);
980                             count != 0; count--, addr1 -= 4, addr2 -= 4)
981                                 *(volatile u_int32_t *)(addr2) =
982                                     *(volatile u_int32_t *)(addr1);
983                 }
984         }
985 }
986
987 #if 0   /* Cause a link error for bus_space_copy_8 */
988 #define bus_space_copy_region_8 !!! bus_space_copy_region_8 unimplemented !!!
989 #endif
990
991 /*
992  * Bus read/write barrier methods.
993  *
994  *      void bus_space_barrier(bus_space_tag_t tag, bus_space_handle_t bsh,
995  *                             bus_size_t offset, bus_size_t len, int flags);
996  *
997  *
998  * Note that BUS_SPACE_BARRIER_WRITE doesn't do anything other than
999  * prevent reordering by the compiler; all Intel x86 processors currently
1000  * retire operations outside the CPU in program order.
1001  */
1002 #define BUS_SPACE_BARRIER_READ  0x01            /* force read barrier */
1003 #define BUS_SPACE_BARRIER_WRITE 0x02            /* force write barrier */
1004
1005 static __inline void
1006 bus_space_barrier(bus_space_tag_t tag __unused, bus_space_handle_t bsh __unused,
1007                   bus_size_t offset __unused, bus_size_t len __unused, int flags)
1008 {
1009 #ifdef __GNUCLIKE_ASM
1010         if (flags & BUS_SPACE_BARRIER_READ)
1011 #ifdef __amd64__
1012                 __asm __volatile("lock; addl $0,0(%%rsp)" : : : "memory");
1013 #else
1014                 __asm __volatile("lock; addl $0,0(%%esp)" : : : "memory");
1015 #endif
1016         else
1017                 __asm __volatile("" : : : "memory");
1018 #endif
1019 }
1020
1021 #ifdef BUS_SPACE_NO_LEGACY
1022 #undef inb
1023 #undef outb
1024 #define inb(a) compiler_error
1025 #define inw(a) compiler_error
1026 #define inl(a) compiler_error
1027 #define outb(a, b) compiler_error
1028 #define outw(a, b) compiler_error
1029 #define outl(a, b) compiler_error
1030 #endif
1031
1032 #include <machine/bus_dma.h>
1033
1034 /*
1035  * Stream accesses are the same as normal accesses on x86; there are no
1036  * supported bus systems with an endianess different from the host one.
1037  */
1038 #define bus_space_read_stream_1(t, h, o)        bus_space_read_1((t), (h), (o))
1039 #define bus_space_read_stream_2(t, h, o)        bus_space_read_2((t), (h), (o))
1040 #define bus_space_read_stream_4(t, h, o)        bus_space_read_4((t), (h), (o))
1041
1042 #define bus_space_read_multi_stream_1(t, h, o, a, c) \
1043         bus_space_read_multi_1((t), (h), (o), (a), (c))
1044 #define bus_space_read_multi_stream_2(t, h, o, a, c) \
1045         bus_space_read_multi_2((t), (h), (o), (a), (c))
1046 #define bus_space_read_multi_stream_4(t, h, o, a, c) \
1047         bus_space_read_multi_4((t), (h), (o), (a), (c))
1048
1049 #define bus_space_write_stream_1(t, h, o, v) \
1050         bus_space_write_1((t), (h), (o), (v))
1051 #define bus_space_write_stream_2(t, h, o, v) \
1052         bus_space_write_2((t), (h), (o), (v))
1053 #define bus_space_write_stream_4(t, h, o, v) \
1054         bus_space_write_4((t), (h), (o), (v))
1055
1056 #define bus_space_write_multi_stream_1(t, h, o, a, c) \
1057         bus_space_write_multi_1((t), (h), (o), (a), (c))
1058 #define bus_space_write_multi_stream_2(t, h, o, a, c) \
1059         bus_space_write_multi_2((t), (h), (o), (a), (c))
1060 #define bus_space_write_multi_stream_4(t, h, o, a, c) \
1061         bus_space_write_multi_4((t), (h), (o), (a), (c))
1062
1063 #define bus_space_set_multi_stream_1(t, h, o, v, c) \
1064         bus_space_set_multi_1((t), (h), (o), (v), (c))
1065 #define bus_space_set_multi_stream_2(t, h, o, v, c) \
1066         bus_space_set_multi_2((t), (h), (o), (v), (c))
1067 #define bus_space_set_multi_stream_4(t, h, o, v, c) \
1068         bus_space_set_multi_4((t), (h), (o), (v), (c))
1069
1070 #define bus_space_read_region_stream_1(t, h, o, a, c) \
1071         bus_space_read_region_1((t), (h), (o), (a), (c))
1072 #define bus_space_read_region_stream_2(t, h, o, a, c) \
1073         bus_space_read_region_2((t), (h), (o), (a), (c))
1074 #define bus_space_read_region_stream_4(t, h, o, a, c) \
1075         bus_space_read_region_4((t), (h), (o), (a), (c))
1076
1077 #define bus_space_write_region_stream_1(t, h, o, a, c) \
1078         bus_space_write_region_1((t), (h), (o), (a), (c))
1079 #define bus_space_write_region_stream_2(t, h, o, a, c) \
1080         bus_space_write_region_2((t), (h), (o), (a), (c))
1081 #define bus_space_write_region_stream_4(t, h, o, a, c) \
1082         bus_space_write_region_4((t), (h), (o), (a), (c))
1083
1084 #define bus_space_set_region_stream_1(t, h, o, v, c) \
1085         bus_space_set_region_1((t), (h), (o), (v), (c))
1086 #define bus_space_set_region_stream_2(t, h, o, v, c) \
1087         bus_space_set_region_2((t), (h), (o), (v), (c))
1088 #define bus_space_set_region_stream_4(t, h, o, v, c) \
1089         bus_space_set_region_4((t), (h), (o), (v), (c))
1090
1091 #define bus_space_copy_region_stream_1(t, h1, o1, h2, o2, c) \
1092         bus_space_copy_region_1((t), (h1), (o1), (h2), (o2), (c))
1093 #define bus_space_copy_region_stream_2(t, h1, o1, h2, o2, c) \
1094         bus_space_copy_region_2((t), (h1), (o1), (h2), (o2), (c))
1095 #define bus_space_copy_region_stream_4(t, h1, o1, h2, o2, c) \
1096         bus_space_copy_region_4((t), (h1), (o1), (h2), (o2), (c))
1097
1098 #endif /* _X86_BUS_H_ */