1 // SPDX-License-Identifier: GPL-2.0 1 // SPDX-License-Identifier: GPL-2.0 2 /* 2 /* 3 * Copyright (C) 2020-2022 Loongson Technology !! 3 * Alpha IO and memory functions. 4 */ 4 */ 5 #include <linux/export.h> !! 5 >> 6 #include <linux/kernel.h> 6 #include <linux/types.h> 7 #include <linux/types.h> 7 #include <linux/io.h> !! 8 #include <linux/string.h> >> 9 #include <linux/module.h> >> 10 #include <asm/io.h> >> 11 >> 12 /* Out-of-line versions of the i/o routines that redirect into the >> 13 platform-specific version. Note that "platform-specific" may mean >> 14 "generic", which bumps through the machine vector. */ >> 15 >> 16 unsigned int >> 17 ioread8(const void __iomem *addr) >> 18 { >> 19 unsigned int ret; >> 20 mb(); >> 21 ret = IO_CONCAT(__IO_PREFIX,ioread8)(addr); >> 22 mb(); >> 23 return ret; >> 24 } >> 25 >> 26 unsigned int ioread16(const void __iomem *addr) >> 27 { >> 28 unsigned int ret; >> 29 mb(); >> 30 ret = IO_CONCAT(__IO_PREFIX,ioread16)(addr); >> 31 mb(); >> 32 return ret; >> 33 } >> 34 >> 35 unsigned int ioread32(const void __iomem *addr) >> 36 { >> 37 unsigned int ret; >> 38 mb(); >> 39 ret = IO_CONCAT(__IO_PREFIX,ioread32)(addr); >> 40 mb(); >> 41 return ret; >> 42 } >> 43 >> 44 u64 ioread64(const void __iomem *addr) >> 45 { >> 46 unsigned int ret; >> 47 mb(); >> 48 ret = IO_CONCAT(__IO_PREFIX,ioread64)(addr); >> 49 mb(); >> 50 return ret; >> 51 } >> 52 >> 53 void iowrite8(u8 b, void __iomem *addr) >> 54 { >> 55 mb(); >> 56 IO_CONCAT(__IO_PREFIX,iowrite8)(b, addr); >> 57 } >> 58 >> 59 void iowrite16(u16 b, void __iomem *addr) >> 60 { >> 61 mb(); >> 62 IO_CONCAT(__IO_PREFIX,iowrite16)(b, addr); >> 63 } >> 64 >> 65 void iowrite32(u32 b, void __iomem *addr) >> 66 { >> 67 mb(); >> 68 IO_CONCAT(__IO_PREFIX,iowrite32)(b, addr); >> 69 } >> 70 >> 71 void iowrite64(u64 b, void __iomem *addr) >> 72 { >> 73 mb(); >> 74 IO_CONCAT(__IO_PREFIX,iowrite64)(b, addr); >> 75 } >> 76 >> 77 EXPORT_SYMBOL(ioread8); >> 78 EXPORT_SYMBOL(ioread16); >> 79 EXPORT_SYMBOL(ioread32); >> 80 EXPORT_SYMBOL(ioread64); >> 81 EXPORT_SYMBOL(iowrite8); >> 82 EXPORT_SYMBOL(iowrite16); >> 83 EXPORT_SYMBOL(iowrite32); >> 84 EXPORT_SYMBOL(iowrite64); >> 85 >> 86 u8 inb(unsigned long port) >> 87 { >> 88 return ioread8(ioport_map(port, 1)); >> 89 } >> 90 >> 91 u16 inw(unsigned long port) >> 92 { >> 93 return ioread16(ioport_map(port, 2)); >> 94 } >> 95 >> 96 u32 inl(unsigned long port) >> 97 { >> 98 return ioread32(ioport_map(port, 4)); >> 99 } >> 100 >> 101 void outb(u8 b, unsigned long port) >> 102 { >> 103 iowrite8(b, ioport_map(port, 1)); >> 104 } >> 105 >> 106 void outw(u16 b, unsigned long port) >> 107 { >> 108 iowrite16(b, ioport_map(port, 2)); >> 109 } >> 110 >> 111 void outl(u32 b, unsigned long port) >> 112 { >> 113 iowrite32(b, ioport_map(port, 4)); >> 114 } >> 115 >> 116 EXPORT_SYMBOL(inb); >> 117 EXPORT_SYMBOL(inw); >> 118 EXPORT_SYMBOL(inl); >> 119 EXPORT_SYMBOL(outb); >> 120 EXPORT_SYMBOL(outw); >> 121 EXPORT_SYMBOL(outl); >> 122 >> 123 u8 __raw_readb(const volatile void __iomem *addr) >> 124 { >> 125 return IO_CONCAT(__IO_PREFIX,readb)(addr); >> 126 } >> 127 >> 128 u16 __raw_readw(const volatile void __iomem *addr) >> 129 { >> 130 return IO_CONCAT(__IO_PREFIX,readw)(addr); >> 131 } >> 132 >> 133 u32 __raw_readl(const volatile void __iomem *addr) >> 134 { >> 135 return IO_CONCAT(__IO_PREFIX,readl)(addr); >> 136 } >> 137 >> 138 u64 __raw_readq(const volatile void __iomem *addr) >> 139 { >> 140 return IO_CONCAT(__IO_PREFIX,readq)(addr); >> 141 } >> 142 >> 143 void __raw_writeb(u8 b, volatile void __iomem *addr) >> 144 { >> 145 IO_CONCAT(__IO_PREFIX,writeb)(b, addr); >> 146 } >> 147 >> 148 void __raw_writew(u16 b, volatile void __iomem *addr) >> 149 { >> 150 IO_CONCAT(__IO_PREFIX,writew)(b, addr); >> 151 } >> 152 >> 153 void __raw_writel(u32 b, volatile void __iomem *addr) >> 154 { >> 155 IO_CONCAT(__IO_PREFIX,writel)(b, addr); >> 156 } >> 157 >> 158 void __raw_writeq(u64 b, volatile void __iomem *addr) >> 159 { >> 160 IO_CONCAT(__IO_PREFIX,writeq)(b, addr); >> 161 } >> 162 >> 163 EXPORT_SYMBOL(__raw_readb); >> 164 EXPORT_SYMBOL(__raw_readw); >> 165 EXPORT_SYMBOL(__raw_readl); >> 166 EXPORT_SYMBOL(__raw_readq); >> 167 EXPORT_SYMBOL(__raw_writeb); >> 168 EXPORT_SYMBOL(__raw_writew); >> 169 EXPORT_SYMBOL(__raw_writel); >> 170 EXPORT_SYMBOL(__raw_writeq); >> 171 >> 172 u8 readb(const volatile void __iomem *addr) >> 173 { >> 174 u8 ret; >> 175 mb(); >> 176 ret = __raw_readb(addr); >> 177 mb(); >> 178 return ret; >> 179 } >> 180 >> 181 u16 readw(const volatile void __iomem *addr) >> 182 { >> 183 u16 ret; >> 184 mb(); >> 185 ret = __raw_readw(addr); >> 186 mb(); >> 187 return ret; >> 188 } >> 189 >> 190 u32 readl(const volatile void __iomem *addr) >> 191 { >> 192 u32 ret; >> 193 mb(); >> 194 ret = __raw_readl(addr); >> 195 mb(); >> 196 return ret; >> 197 } >> 198 >> 199 u64 readq(const volatile void __iomem *addr) >> 200 { >> 201 u64 ret; >> 202 mb(); >> 203 ret = __raw_readq(addr); >> 204 mb(); >> 205 return ret; >> 206 } >> 207 >> 208 void writeb(u8 b, volatile void __iomem *addr) >> 209 { >> 210 mb(); >> 211 __raw_writeb(b, addr); >> 212 } >> 213 >> 214 void writew(u16 b, volatile void __iomem *addr) >> 215 { >> 216 mb(); >> 217 __raw_writew(b, addr); >> 218 } >> 219 >> 220 void writel(u32 b, volatile void __iomem *addr) >> 221 { >> 222 mb(); >> 223 __raw_writel(b, addr); >> 224 } >> 225 >> 226 void writeq(u64 b, volatile void __iomem *addr) >> 227 { >> 228 mb(); >> 229 __raw_writeq(b, addr); >> 230 } >> 231 >> 232 EXPORT_SYMBOL(readb); >> 233 EXPORT_SYMBOL(readw); >> 234 EXPORT_SYMBOL(readl); >> 235 EXPORT_SYMBOL(readq); >> 236 EXPORT_SYMBOL(writeb); >> 237 EXPORT_SYMBOL(writew); >> 238 EXPORT_SYMBOL(writel); >> 239 EXPORT_SYMBOL(writeq); 8 240 9 /* 241 /* 10 * Copy data from IO memory space to "real" me !! 242 * The _relaxed functions must be ordered w.r.t. each other, but they don't >> 243 * have to be ordered w.r.t. other memory accesses. 11 */ 244 */ 12 void __memcpy_fromio(void *to, const volatile !! 245 u8 readb_relaxed(const volatile void __iomem *addr) 13 { 246 { 14 while (count && !IS_ALIGNED((unsigned !! 247 mb(); 15 *(u8 *)to = __raw_readb(from); !! 248 return __raw_readb(addr); 16 from++; !! 249 } 17 to++; !! 250 >> 251 u16 readw_relaxed(const volatile void __iomem *addr) >> 252 { >> 253 mb(); >> 254 return __raw_readw(addr); >> 255 } >> 256 >> 257 u32 readl_relaxed(const volatile void __iomem *addr) >> 258 { >> 259 mb(); >> 260 return __raw_readl(addr); >> 261 } >> 262 >> 263 u64 readq_relaxed(const volatile void __iomem *addr) >> 264 { >> 265 mb(); >> 266 return __raw_readq(addr); >> 267 } >> 268 >> 269 EXPORT_SYMBOL(readb_relaxed); >> 270 EXPORT_SYMBOL(readw_relaxed); >> 271 EXPORT_SYMBOL(readl_relaxed); >> 272 EXPORT_SYMBOL(readq_relaxed); >> 273 >> 274 /* >> 275 * Read COUNT 8-bit bytes from port PORT into memory starting at SRC. >> 276 */ >> 277 void ioread8_rep(const void __iomem *port, void *dst, unsigned long count) >> 278 { >> 279 while ((unsigned long)dst & 0x3) { >> 280 if (!count) >> 281 return; 18 count--; 282 count--; >> 283 *(unsigned char *)dst = ioread8(port); >> 284 dst += 1; 19 } 285 } 20 286 21 while (count >= 8) { !! 287 while (count >= 4) { 22 *(u64 *)to = __raw_readq(from) !! 288 unsigned int w; 23 from += 8; !! 289 count -= 4; 24 to += 8; !! 290 w = ioread8(port); 25 count -= 8; !! 291 w |= ioread8(port) << 8; >> 292 w |= ioread8(port) << 16; >> 293 w |= ioread8(port) << 24; >> 294 *(unsigned int *)dst = w; >> 295 dst += 4; 26 } 296 } 27 297 28 while (count) { 298 while (count) { 29 *(u8 *)to = __raw_readb(from); !! 299 --count; 30 from++; !! 300 *(unsigned char *)dst = ioread8(port); 31 to++; !! 301 dst += 1; 32 count--; << 33 } 302 } 34 } 303 } 35 EXPORT_SYMBOL(__memcpy_fromio); !! 304 >> 305 void insb(unsigned long port, void *dst, unsigned long count) >> 306 { >> 307 ioread8_rep(ioport_map(port, 1), dst, count); >> 308 } >> 309 >> 310 EXPORT_SYMBOL(ioread8_rep); >> 311 EXPORT_SYMBOL(insb); 36 312 37 /* 313 /* 38 * Copy data from "real" memory space to IO me !! 314 * Read COUNT 16-bit words from port PORT into memory starting at >> 315 * SRC. SRC must be at least short aligned. This is used by the >> 316 * IDE driver to read disk sectors. Performance is important, but >> 317 * the interfaces seems to be slow: just using the inlined version >> 318 * of the inw() breaks things. 39 */ 319 */ 40 void __memcpy_toio(volatile void __iomem *to, !! 320 void ioread16_rep(const void __iomem *port, void *dst, unsigned long count) 41 { 321 { 42 while (count && !IS_ALIGNED((unsigned !! 322 if (unlikely((unsigned long)dst & 0x3)) { 43 __raw_writeb(*(u8 *)from, to); !! 323 if (!count) 44 from++; !! 324 return; 45 to++; !! 325 BUG_ON((unsigned long)dst & 0x1); 46 count--; 326 count--; >> 327 *(unsigned short *)dst = ioread16(port); >> 328 dst += 2; 47 } 329 } 48 330 49 while (count >= 8) { !! 331 while (count >= 2) { 50 __raw_writeq(*(u64 *)from, to) !! 332 unsigned int w; 51 from += 8; !! 333 count -= 2; 52 to += 8; !! 334 w = ioread16(port); >> 335 w |= ioread16(port) << 16; >> 336 *(unsigned int *)dst = w; >> 337 dst += 4; >> 338 } >> 339 >> 340 if (count) { >> 341 *(unsigned short*)dst = ioread16(port); >> 342 } >> 343 } >> 344 >> 345 void insw(unsigned long port, void *dst, unsigned long count) >> 346 { >> 347 ioread16_rep(ioport_map(port, 2), dst, count); >> 348 } >> 349 >> 350 EXPORT_SYMBOL(ioread16_rep); >> 351 EXPORT_SYMBOL(insw); >> 352 >> 353 >> 354 /* >> 355 * Read COUNT 32-bit words from port PORT into memory starting at >> 356 * SRC. Now works with any alignment in SRC. Performance is important, >> 357 * but the interfaces seems to be slow: just using the inlined version >> 358 * of the inl() breaks things. >> 359 */ >> 360 void ioread32_rep(const void __iomem *port, void *dst, unsigned long count) >> 361 { >> 362 if (unlikely((unsigned long)dst & 0x3)) { >> 363 while (count--) { >> 364 struct S { int x __attribute__((packed)); }; >> 365 ((struct S *)dst)->x = ioread32(port); >> 366 dst += 4; >> 367 } >> 368 } else { >> 369 /* Buffer 32-bit aligned. */ >> 370 while (count--) { >> 371 *(unsigned int *)dst = ioread32(port); >> 372 dst += 4; >> 373 } >> 374 } >> 375 } >> 376 >> 377 void insl(unsigned long port, void *dst, unsigned long count) >> 378 { >> 379 ioread32_rep(ioport_map(port, 4), dst, count); >> 380 } >> 381 >> 382 EXPORT_SYMBOL(ioread32_rep); >> 383 EXPORT_SYMBOL(insl); >> 384 >> 385 >> 386 /* >> 387 * Like insb but in the opposite direction. >> 388 * Don't worry as much about doing aligned memory transfers: >> 389 * doing byte reads the "slow" way isn't nearly as slow as >> 390 * doing byte writes the slow way (no r-m-w cycle). >> 391 */ >> 392 void iowrite8_rep(void __iomem *port, const void *xsrc, unsigned long count) >> 393 { >> 394 const unsigned char *src = xsrc; >> 395 while (count--) >> 396 iowrite8(*src++, port); >> 397 } >> 398 >> 399 void outsb(unsigned long port, const void *src, unsigned long count) >> 400 { >> 401 iowrite8_rep(ioport_map(port, 1), src, count); >> 402 } >> 403 >> 404 EXPORT_SYMBOL(iowrite8_rep); >> 405 EXPORT_SYMBOL(outsb); >> 406 >> 407 >> 408 /* >> 409 * Like insw but in the opposite direction. This is used by the IDE >> 410 * driver to write disk sectors. Performance is important, but the >> 411 * interfaces seems to be slow: just using the inlined version of the >> 412 * outw() breaks things. >> 413 */ >> 414 void iowrite16_rep(void __iomem *port, const void *src, unsigned long count) >> 415 { >> 416 if (unlikely((unsigned long)src & 0x3)) { >> 417 if (!count) >> 418 return; >> 419 BUG_ON((unsigned long)src & 0x1); >> 420 iowrite16(*(unsigned short *)src, port); >> 421 src += 2; >> 422 --count; >> 423 } >> 424 >> 425 while (count >= 2) { >> 426 unsigned int w; >> 427 count -= 2; >> 428 w = *(unsigned int *)src; >> 429 src += 4; >> 430 iowrite16(w >> 0, port); >> 431 iowrite16(w >> 16, port); >> 432 } >> 433 >> 434 if (count) { >> 435 iowrite16(*(unsigned short *)src, port); >> 436 } >> 437 } >> 438 >> 439 void outsw(unsigned long port, const void *src, unsigned long count) >> 440 { >> 441 iowrite16_rep(ioport_map(port, 2), src, count); >> 442 } >> 443 >> 444 EXPORT_SYMBOL(iowrite16_rep); >> 445 EXPORT_SYMBOL(outsw); >> 446 >> 447 >> 448 /* >> 449 * Like insl but in the opposite direction. This is used by the IDE >> 450 * driver to write disk sectors. Works with any alignment in SRC. >> 451 * Performance is important, but the interfaces seems to be slow: >> 452 * just using the inlined version of the outl() breaks things. >> 453 */ >> 454 void iowrite32_rep(void __iomem *port, const void *src, unsigned long count) >> 455 { >> 456 if (unlikely((unsigned long)src & 0x3)) { >> 457 while (count--) { >> 458 struct S { int x __attribute__((packed)); }; >> 459 iowrite32(((struct S *)src)->x, port); >> 460 src += 4; >> 461 } >> 462 } else { >> 463 /* Buffer 32-bit aligned. */ >> 464 while (count--) { >> 465 iowrite32(*(unsigned int *)src, port); >> 466 src += 4; >> 467 } >> 468 } >> 469 } >> 470 >> 471 void outsl(unsigned long port, const void *src, unsigned long count) >> 472 { >> 473 iowrite32_rep(ioport_map(port, 4), src, count); >> 474 } >> 475 >> 476 EXPORT_SYMBOL(iowrite32_rep); >> 477 EXPORT_SYMBOL(outsl); >> 478 >> 479 >> 480 /* >> 481 * Copy data from IO memory space to "real" memory space. >> 482 * This needs to be optimized. >> 483 */ >> 484 void memcpy_fromio(void *to, const volatile void __iomem *from, long count) >> 485 { >> 486 /* Optimize co-aligned transfers. Everything else gets handled >> 487 a byte at a time. */ >> 488 >> 489 if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) { 53 count -= 8; 490 count -= 8; >> 491 do { >> 492 *(u64 *)to = __raw_readq(from); >> 493 count -= 8; >> 494 to += 8; >> 495 from += 8; >> 496 } while (count >= 0); >> 497 count += 8; 54 } 498 } 55 499 56 while (count) { !! 500 if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) { 57 __raw_writeb(*(u8 *)from, to); !! 501 count -= 4; 58 from++; !! 502 do { >> 503 *(u32 *)to = __raw_readl(from); >> 504 count -= 4; >> 505 to += 4; >> 506 from += 4; >> 507 } while (count >= 0); >> 508 count += 4; >> 509 } >> 510 >> 511 if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) { >> 512 count -= 2; >> 513 do { >> 514 *(u16 *)to = __raw_readw(from); >> 515 count -= 2; >> 516 to += 2; >> 517 from += 2; >> 518 } while (count >= 0); >> 519 count += 2; >> 520 } >> 521 >> 522 while (count > 0) { >> 523 *(u8 *) to = __raw_readb(from); >> 524 count--; 59 to++; 525 to++; >> 526 from++; >> 527 } >> 528 mb(); >> 529 } >> 530 >> 531 EXPORT_SYMBOL(memcpy_fromio); >> 532 >> 533 >> 534 /* >> 535 * Copy data from "real" memory space to IO memory space. >> 536 * This needs to be optimized. >> 537 */ >> 538 void memcpy_toio(volatile void __iomem *to, const void *from, long count) >> 539 { >> 540 /* Optimize co-aligned transfers. Everything else gets handled >> 541 a byte at a time. */ >> 542 /* FIXME -- align FROM. */ >> 543 >> 544 if (count >= 8 && ((u64)to & 7) == ((u64)from & 7)) { >> 545 count -= 8; >> 546 do { >> 547 __raw_writeq(*(const u64 *)from, to); >> 548 count -= 8; >> 549 to += 8; >> 550 from += 8; >> 551 } while (count >= 0); >> 552 count += 8; >> 553 } >> 554 >> 555 if (count >= 4 && ((u64)to & 3) == ((u64)from & 3)) { >> 556 count -= 4; >> 557 do { >> 558 __raw_writel(*(const u32 *)from, to); >> 559 count -= 4; >> 560 to += 4; >> 561 from += 4; >> 562 } while (count >= 0); >> 563 count += 4; >> 564 } >> 565 >> 566 if (count >= 2 && ((u64)to & 1) == ((u64)from & 1)) { >> 567 count -= 2; >> 568 do { >> 569 __raw_writew(*(const u16 *)from, to); >> 570 count -= 2; >> 571 to += 2; >> 572 from += 2; >> 573 } while (count >= 0); >> 574 count += 2; >> 575 } >> 576 >> 577 while (count > 0) { >> 578 __raw_writeb(*(const u8 *) from, to); 60 count--; 579 count--; >> 580 to++; >> 581 from++; 61 } 582 } >> 583 mb(); 62 } 584 } 63 EXPORT_SYMBOL(__memcpy_toio); !! 585 >> 586 EXPORT_SYMBOL(memcpy_toio); >> 587 64 588 65 /* 589 /* 66 * "memset" on IO memory space. 590 * "memset" on IO memory space. 67 */ 591 */ 68 void __memset_io(volatile void __iomem *dst, i !! 592 void _memset_c_io(volatile void __iomem *to, unsigned long c, long count) 69 { 593 { 70 u64 qc = (u8)c; !! 594 /* Handle any initial odd byte */ >> 595 if (count > 0 && ((u64)to & 1)) { >> 596 __raw_writeb(c, to); >> 597 to++; >> 598 count--; >> 599 } 71 600 72 qc |= qc << 8; !! 601 /* Handle any initial odd halfword */ 73 qc |= qc << 16; !! 602 if (count >= 2 && ((u64)to & 2)) { 74 qc |= qc << 32; !! 603 __raw_writew(c, to); >> 604 to += 2; >> 605 count -= 2; >> 606 } 75 607 76 while (count && !IS_ALIGNED((unsigned !! 608 /* Handle any initial odd word */ 77 __raw_writeb(c, dst); !! 609 if (count >= 4 && ((u64)to & 4)) { 78 dst++; !! 610 __raw_writel(c, to); 79 count--; !! 611 to += 4; >> 612 count -= 4; 80 } 613 } 81 614 82 while (count >= 8) { !! 615 /* Handle all full-sized quadwords: we're aligned 83 __raw_writeq(qc, dst); !! 616 (or have a small count) */ 84 dst += 8; !! 617 count -= 8; 85 count -= 8; !! 618 if (count >= 0) { >> 619 do { >> 620 __raw_writeq(c, to); >> 621 to += 8; >> 622 count -= 8; >> 623 } while (count >= 0); 86 } 624 } >> 625 count += 8; 87 626 88 while (count) { !! 627 /* The tail is word-aligned if we still have count >= 4 */ 89 __raw_writeb(c, dst); !! 628 if (count >= 4) { 90 dst++; !! 629 __raw_writel(c, to); 91 count--; !! 630 to += 4; >> 631 count -= 4; >> 632 } >> 633 >> 634 /* The tail is half-word aligned if we have count >= 2 */ >> 635 if (count >= 2) { >> 636 __raw_writew(c, to); >> 637 to += 2; >> 638 count -= 2; >> 639 } >> 640 >> 641 /* And finally, one last byte.. */ >> 642 if (count) { >> 643 __raw_writeb(c, to); >> 644 } >> 645 mb(); >> 646 } >> 647 >> 648 EXPORT_SYMBOL(_memset_c_io); >> 649 >> 650 #if IS_ENABLED(CONFIG_VGA_CONSOLE) || IS_ENABLED(CONFIG_MDA_CONSOLE) >> 651 >> 652 #include <asm/vga.h> >> 653 >> 654 /* A version of memcpy used by the vga console routines to move data around >> 655 arbitrarily between screen and main memory. */ >> 656 >> 657 void >> 658 scr_memcpyw(u16 *d, const u16 *s, unsigned int count) >> 659 { >> 660 const u16 __iomem *ios = (const u16 __iomem *) s; >> 661 u16 __iomem *iod = (u16 __iomem *) d; >> 662 int s_isio = __is_ioaddr(s); >> 663 int d_isio = __is_ioaddr(d); >> 664 >> 665 if (s_isio) { >> 666 if (d_isio) { >> 667 /* FIXME: Should handle unaligned ops and >> 668 operation widening. */ >> 669 >> 670 count /= 2; >> 671 while (count--) { >> 672 u16 tmp = __raw_readw(ios++); >> 673 __raw_writew(tmp, iod++); >> 674 } >> 675 } >> 676 else >> 677 memcpy_fromio(d, ios, count); >> 678 } else { >> 679 if (d_isio) >> 680 memcpy_toio(iod, s, count); >> 681 else >> 682 memcpy(d, s, count); >> 683 } >> 684 } >> 685 >> 686 EXPORT_SYMBOL(scr_memcpyw); >> 687 >> 688 void scr_memmovew(u16 *d, const u16 *s, unsigned int count) >> 689 { >> 690 if (d < s) >> 691 scr_memcpyw(d, s, count); >> 692 else { >> 693 count /= 2; >> 694 d += count; >> 695 s += count; >> 696 while (count--) >> 697 scr_writew(scr_readw(--s), --d); 92 } 698 } 93 } 699 } 94 EXPORT_SYMBOL(__memset_io); !! 700 EXPORT_SYMBOL(scr_memmovew); >> 701 #endif >> 702 >> 703 void __iomem *ioport_map(unsigned long port, unsigned int size) >> 704 { >> 705 return IO_CONCAT(__IO_PREFIX,ioportmap) (port); >> 706 } >> 707 >> 708 void ioport_unmap(void __iomem *addr) >> 709 { >> 710 } >> 711 >> 712 EXPORT_SYMBOL(ioport_map); >> 713 EXPORT_SYMBOL(ioport_unmap); 95 714
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.