1 /* $NetBSD: ebus.c,v 1.9 2000/05/17 09:25:27 mrg Exp $ */ 2 3 /* 4 * Copyright (c) 1999, 2000 Matthew R. Green 5 * All rights reserved. 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 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include "opt_ddb.h" 32 33 /* 34 * UltraSPARC 5 and beyond ebus support. 35 * 36 * note that this driver is far from complete: 37 * - ebus2 dma code is completely unwritten 38 * - interrupt establish code is completely unwritten 39 * - bus map code is written and appears to work 40 */ 41 42 #undef DEBUG 43 #define DEBUG 44 45 #ifdef DEBUG 46 #define EDB_PROM 0x01 47 #define EDB_CHILD 0x02 48 #define EDB_INTRMAP 0x04 49 #define EDB_BUSMAP 0x08 50 #define EDB_BUSDMA 0x10 51 #define EDB_INTR 0x20 52 int ebus_debug = 0; 53 #define DPRINTF(l, s) do { if (ebus_debug & l) printf s; } while (0) 54 #else 55 #define DPRINTF(l, s) 56 #endif 57 58 #include <sys/param.h> 59 #include <sys/conf.h> 60 #include <sys/device.h> 61 #include <sys/errno.h> 62 #include <sys/extent.h> 63 #include <sys/malloc.h> 64 #include <sys/systm.h> 65 #include <sys/time.h> 66 67 #include <vm/vm.h> 68 #include <vm/vm_kern.h> 69 70 #define _SPARC_BUS_DMA_PRIVATE 71 #include <machine/bus.h> 72 #include <machine/autoconf.h> 73 74 #include <dev/pci/pcivar.h> 75 #include <dev/pci/pcireg.h> 76 #include <dev/pci/pcidevs.h> 77 78 #include <sparc64/dev/iommureg.h> 79 #include <sparc64/dev/iommuvar.h> 80 #include <sparc64/dev/psychoreg.h> 81 #include <sparc64/dev/psychovar.h> 82 #include <sparc64/dev/ebusreg.h> 83 #include <sparc64/dev/ebusvar.h> 84 #include <sparc64/sparc64/cache.h> 85 86 int ebus_match __P((struct device *, struct cfdata *, void *)); 87 void ebus_attach __P((struct device *, struct device *, void *)); 88 89 struct cfattach ebus_ca = { 90 sizeof(struct device), ebus_match, ebus_attach 91 }; 92 93 int ebus_setup_attach_args __P((struct ebus_softc *, int, 94 struct ebus_attach_args *)); 95 void ebus_destroy_attach_args __P((struct ebus_attach_args *)); 96 int ebus_print __P((void *, const char *)); 97 void ebus_find_ino __P((struct ebus_softc *, struct ebus_attach_args *)); 98 int ebus_find_node __P((struct ebus_softc *, struct pci_attach_args *)); 99 100 /* 101 * here are our bus space and bus dma routines. 102 */ 103 static int ebus_bus_mmap __P((bus_space_tag_t, bus_type_t, bus_addr_t, 104 int, bus_space_handle_t *)); 105 static int _ebus_bus_map __P((bus_space_tag_t, bus_type_t, bus_addr_t, 106 bus_size_t, int, vaddr_t, 107 bus_space_handle_t *)); 108 static void *ebus_intr_establish __P((bus_space_tag_t, int, int, 109 int (*) __P((void *)), void *)); 110 111 static int ebus_dmamap_load __P((bus_dma_tag_t, bus_dmamap_t, void *, 112 bus_size_t, struct proc *, int)); 113 static void ebus_dmamap_unload __P((bus_dma_tag_t, bus_dmamap_t)); 114 static void ebus_dmamap_sync __P((bus_dma_tag_t, bus_dmamap_t, bus_addr_t, 115 bus_size_t, int)); 116 int ebus_dmamem_alloc __P((bus_dma_tag_t, bus_size_t, bus_size_t, bus_size_t, 117 bus_dma_segment_t *, int, int *, int)); 118 void ebus_dmamem_free __P((bus_dma_tag_t, bus_dma_segment_t *, int)); 119 int ebus_dmamem_map __P((bus_dma_tag_t, bus_dma_segment_t *, int, size_t, 120 caddr_t *, int)); 121 void ebus_dmamem_unmap __P((bus_dma_tag_t, caddr_t, size_t)); 122 123 int 124 ebus_match(parent, match, aux) 125 struct device *parent; 126 struct cfdata *match; 127 void *aux; 128 { 129 struct pci_attach_args *pa = aux; 130 131 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE && 132 PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN && 133 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_EBUS) 134 return (1); 135 136 return (0); 137 } 138 139 /* 140 * attach an ebus and all it's children. this code is modeled 141 * after the sbus code which does similar things. 142 */ 143 void 144 ebus_attach(parent, self, aux) 145 struct device *parent, *self; 146 void *aux; 147 { 148 struct ebus_softc *sc = (struct ebus_softc *)self; 149 struct pci_attach_args *pa = aux; 150 struct ebus_attach_args eba; 151 struct ebus_interrupt_map_mask *immp; 152 int node, nmapmask, rv; 153 char devinfo[256]; 154 155 printf("\n"); 156 157 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo); 158 printf("%s: %s, revision 0x%02x\n", self->dv_xname, devinfo, 159 PCI_REVISION(pa->pa_class)); 160 161 sc->sc_parent = (struct psycho_softc *)parent; 162 sc->sc_bustag = pa->pa_memt; 163 sc->sc_childbustag = ebus_alloc_bus_tag(sc, PCI_MEMORY_BUS_SPACE); 164 sc->sc_dmatag = ebus_alloc_dma_tag(sc, pa->pa_dmat); 165 166 node = ebus_find_node(sc, pa); 167 if (node == 0) 168 panic("could not find ebus node"); 169 170 sc->sc_node = node; 171 172 /* 173 * fill in our softc with information from the prom 174 */ 175 sc->sc_intmap = NULL; 176 sc->sc_range = NULL; 177 rv = getprop(node, "interrupt-map", sizeof(struct ebus_interrupt_map), 178 &sc->sc_nintmap, (void **)&sc->sc_intmap); 179 if (rv) 180 panic("could not get ebus interrupt-map"); 181 182 immp = &sc->sc_intmapmask; 183 rv = getprop(node, "interrupt-map-mask", 184 sizeof(struct ebus_interrupt_map_mask), &nmapmask, 185 (void **)&immp); 186 if (rv) 187 panic("could not get ebus interrupt-map-mask"); 188 if (nmapmask != 1) 189 panic("ebus interrupt-map-mask is broken"); 190 191 rv = getprop(node, "ranges", sizeof(struct ebus_ranges), 192 &sc->sc_nrange, (void **)&sc->sc_range); 193 if (rv) 194 panic("could not get ebus ranges"); 195 196 /* 197 * now attach all our children 198 */ 199 DPRINTF(EDB_CHILD, ("ebus node %08x, searching children...\n", node)); 200 for (node = firstchild(node); node; node = nextsibling(node)) { 201 char *name = getpropstring(node, "name"); 202 203 if (ebus_setup_attach_args(sc, node, &eba) != 0) { 204 printf("ebus_attach: %s: incomplete\n", name); 205 continue; 206 } else { 207 DPRINTF(EDB_CHILD, ("- found child `%s', attaching\n", eba.ea_name)); 208 (void)config_found(self, &eba, ebus_print); 209 } 210 ebus_destroy_attach_args(&eba); 211 } 212 } 213 214 int 215 ebus_setup_attach_args(sc, node, ea) 216 struct ebus_softc *sc; 217 int node; 218 struct ebus_attach_args *ea; 219 { 220 int n, rv; 221 222 bzero(ea, sizeof(struct ebus_attach_args)); 223 rv = getprop(node, "name", 1, &n, (void **)&ea->ea_name); 224 if (rv != 0) 225 return (rv); 226 ea->ea_name[n] = '\0'; 227 228 ea->ea_node = node; 229 ea->ea_bustag = sc->sc_childbustag; 230 ea->ea_dmatag = sc->sc_dmatag; 231 232 rv = getprop(node, "reg", sizeof(struct ebus_regs), &ea->ea_nregs, 233 (void **)&ea->ea_regs); 234 if (rv) 235 return (rv); 236 237 rv = getprop(node, "address", sizeof(u_int32_t), &ea->ea_nvaddrs, 238 (void **)&ea->ea_vaddrs); 239 if (rv != ENOENT) { 240 if (rv) 241 return (rv); 242 243 if (ea->ea_nregs != ea->ea_nvaddrs) 244 printf("ebus loses: device %s: %d regs and %d addrs\n", 245 ea->ea_name, ea->ea_nregs, ea->ea_nvaddrs); 246 } else 247 ea->ea_nvaddrs = 0; 248 249 if (getprop(node, "interrupts", sizeof(u_int32_t), &ea->ea_nintrs, 250 (void **)&ea->ea_intrs)) 251 ea->ea_nintrs = 0; 252 else 253 ebus_find_ino(sc, ea); 254 255 return (0); 256 } 257 258 void 259 ebus_destroy_attach_args(ea) 260 struct ebus_attach_args *ea; 261 { 262 263 if (ea->ea_name) 264 free((void *)ea->ea_name, M_DEVBUF); 265 if (ea->ea_regs) 266 free((void *)ea->ea_regs, M_DEVBUF); 267 if (ea->ea_intrs) 268 free((void *)ea->ea_intrs, M_DEVBUF); 269 if (ea->ea_vaddrs) 270 free((void *)ea->ea_vaddrs, M_DEVBUF); 271 } 272 273 int 274 ebus_print(aux, p) 275 void *aux; 276 const char *p; 277 { 278 struct ebus_attach_args *ea = aux; 279 int i; 280 281 if (p) 282 printf("%s at %s", ea->ea_name, p); 283 for (i = 0; i < ea->ea_nregs; i++) 284 printf(" addr %x-%x", ea->ea_regs[i].lo, 285 ea->ea_regs[i].lo + ea->ea_regs[i].size - 1); 286 for (i = 0; i < ea->ea_nintrs; i++) 287 printf(" ipl %d", ea->ea_intrs[i]); 288 return (UNCONF); 289 } 290 291 /* 292 * find the INO values for each interrupt and fill them in. 293 * 294 * for each "reg" property of this device, mask it's hi and lo 295 * values with the "interrupt-map-mask"'s hi/lo values, and also 296 * mask the interrupt number with the interrupt mask. search the 297 * "interrupt-map" list for matching values of hi, lo and interrupt 298 * to give the INO for this interrupt. 299 */ 300 void 301 ebus_find_ino(sc, ea) 302 struct ebus_softc *sc; 303 struct ebus_attach_args *ea; 304 { 305 u_int32_t hi, lo, intr; 306 int i, j, k; 307 308 DPRINTF(EDB_INTRMAP, ("ebus_find_ino: searching %d interrupts", ea->ea_nintrs)); 309 for (j = 0; j < ea->ea_nintrs; j++) { 310 intr = ea->ea_intrs[j] & sc->sc_intmapmask.intr; 311 312 DPRINTF(EDB_INTRMAP, ("; intr %x masked to %x", ea->ea_intrs[j], intr)); 313 for (i = 0; i < ea->ea_nregs; i++) { 314 hi = ea->ea_regs[i].hi & sc->sc_intmapmask.hi; 315 lo = ea->ea_regs[i].lo & sc->sc_intmapmask.lo; 316 317 DPRINTF(EDB_INTRMAP, ("; reg hi.lo %08x.08x masked to %08x.%08x", ea->ea_regs[i].hi, ea->ea_regs[i].lo, hi, lo)); 318 for (k = 0; k < sc->sc_nintmap; k++) { 319 DPRINTF(EDB_INTRMAP, ("; checking hi.lo %08x.%08x intr %x", sc->sc_intmap[k].hi, sc->sc_intmap[k].lo, sc->sc_intmap[k].intr)); 320 if (hi == sc->sc_intmap[k].hi && 321 lo == sc->sc_intmap[k].lo && 322 intr == sc->sc_intmap[k].intr) { 323 ea->ea_intrs[j] = sc->sc_intmap[k].cintr; 324 DPRINTF(EDB_INTRMAP, ("; FOUND IT! changing to %d\n", sc->sc_intmap[k].cintr)); 325 goto next_intr; 326 } 327 } 328 } 329 next_intr: 330 } 331 } 332 333 /* 334 * what is our OFW node? this depends on our pci chipset tag 335 * having it's "node" value set to the OFW node of the PCI bus, 336 * see the simba driver. 337 */ 338 int 339 ebus_find_node(sc, pa) 340 struct ebus_softc *sc; 341 struct pci_attach_args *pa; 342 { 343 int node = pa->pa_pc->node; 344 int n, *ap; 345 int pcibus, bus, dev, fn; 346 347 DPRINTF(EDB_PROM, ("ebus_find_node: looking at pci node %08x\n", node)); 348 for (node = firstchild(node); node; node = nextsibling(node)) { 349 char *name = getpropstring(node, "name"); 350 351 DPRINTF(EDB_PROM, ("ebus_find_node: looking at PCI device `%s', node = %08x\n", name, node)); 352 /* must be "ebus" */ 353 if (strcmp(name, "ebus") != 0) 354 continue; 355 356 /* pull the PCI bus out of the pa_tag */ 357 pcibus = (pa->pa_tag >> 16) & 0xff; 358 DPRINTF(EDB_PROM, ("; pcibus %d dev %d fn %d\n", pcibus, pa->pa_device, pa->pa_function)); 359 360 /* get the PCI bus/device/function for this node */ 361 ap = NULL; 362 if (getprop(node, "reg", sizeof(int), &n, 363 (void **)&ap)) 364 continue; 365 366 bus = (ap[0] >> 16) & 0xff; 367 dev = (ap[0] >> 11) & 0x1f; 368 fn = (ap[0] >> 8) & 0x7; 369 370 DPRINTF(EDB_PROM, ("; looking for bus %d dev %d fn %d\n", pcibus, pa->pa_device, pa->pa_function)); 371 if (pa->pa_device != dev || 372 pa->pa_function != fn || 373 pcibus != bus) 374 continue; 375 376 DPRINTF(EDB_PROM, ("; found it, returning %08x\n", node)); 377 /* found it! */ 378 free(ap, M_DEVBUF); 379 return (node); 380 } 381 382 /* damn! */ 383 return (0); 384 } 385 386 /* 387 * bus space and bus dma below here 388 */ 389 bus_space_tag_t 390 ebus_alloc_bus_tag(sc, type) 391 struct ebus_softc *sc; 392 int type; 393 { 394 bus_space_tag_t bt; 395 396 bt = (bus_space_tag_t) 397 malloc(sizeof(struct sparc_bus_space_tag), M_DEVBUF, M_NOWAIT); 398 if (bt == NULL) 399 panic("could not allocate ebus bus tag"); 400 401 bzero(bt, sizeof *bt); 402 bt->cookie = sc; 403 bt->parent = sc->sc_bustag; 404 bt->type = type; 405 bt->sparc_bus_map = _ebus_bus_map; 406 bt->sparc_bus_mmap = ebus_bus_mmap; 407 bt->sparc_intr_establish = ebus_intr_establish; 408 return (bt); 409 } 410 411 /* XXX? */ 412 bus_dma_tag_t 413 ebus_alloc_dma_tag(sc, pdt) 414 struct ebus_softc *sc; 415 bus_dma_tag_t pdt; 416 { 417 bus_dma_tag_t dt; 418 419 dt = (bus_dma_tag_t) 420 malloc(sizeof(struct sparc_bus_dma_tag), M_DEVBUF, M_NOWAIT); 421 if (dt == NULL) 422 panic("could not allocate ebus dma tag"); 423 424 bzero(dt, sizeof *dt); 425 dt->_cookie = sc; 426 dt->_parent = pdt; 427 #define PCOPY(x) dt->x = pdt->x 428 PCOPY(_dmamap_create); 429 PCOPY(_dmamap_destroy); 430 dt->_dmamap_load = ebus_dmamap_load; 431 PCOPY(_dmamap_load_mbuf); 432 PCOPY(_dmamap_load_uio); 433 PCOPY(_dmamap_load_raw); 434 dt->_dmamap_unload = ebus_dmamap_unload; 435 dt->_dmamap_sync = ebus_dmamap_sync; 436 dt->_dmamem_alloc = ebus_dmamem_alloc; 437 dt->_dmamem_free = ebus_dmamem_free; 438 dt->_dmamem_map = ebus_dmamem_map; 439 dt->_dmamem_unmap = ebus_dmamem_unmap; 440 PCOPY(_dmamem_mmap); 441 #undef PCOPY 442 return (dt); 443 } 444 445 /* 446 * bus space support. <sparc64/dev/psychoreg.h> has a discussion 447 * about PCI physical addresses, which also applies to ebus. 448 */ 449 static int 450 _ebus_bus_map(t, btype, offset, size, flags, vaddr, hp) 451 bus_space_tag_t t; 452 bus_type_t btype; 453 bus_addr_t offset; 454 bus_size_t size; 455 int flags; 456 vaddr_t vaddr; 457 bus_space_handle_t *hp; 458 { 459 struct ebus_softc *sc = t->cookie; 460 bus_addr_t hi, lo; 461 int i; 462 463 DPRINTF(EDB_BUSMAP, ("\n_ebus_bus_map: type %d off %016llx sz %x flags %d va %p", (int)t->type, (u_int64_t)offset, (int)size, (int)flags, vaddr)); 464 465 hi = offset >> 32UL; 466 lo = offset & 0xffffffff; 467 DPRINTF(EDB_BUSMAP, (" (hi %08x lo %08x)", (u_int)hi, (u_int)lo)); 468 for (i = 0; i < sc->sc_nrange; i++) { 469 bus_addr_t pciaddr; 470 471 if (hi != sc->sc_range[i].child_hi) 472 continue; 473 if (lo < sc->sc_range[i].child_lo || 474 (lo + size) > (sc->sc_range[i].child_lo + sc->sc_range[i].size)) 475 continue; 476 477 pciaddr = ((bus_addr_t)sc->sc_range[i].phys_mid << 32UL) | 478 sc->sc_range[i].phys_lo; 479 pciaddr += lo; 480 DPRINTF(EDB_BUSMAP, ("\n_ebus_bus_map: mapping paddr offset %qx pciaddr %qx\n", 481 offset, pciaddr)); 482 /* pass it onto the psycho */ 483 return (bus_space_map2(sc->sc_bustag, t->type, pciaddr, 484 size, flags, vaddr, hp)); 485 } 486 DPRINTF(EDB_BUSMAP, (": FAILED\n")); 487 return (EINVAL); 488 } 489 490 static int 491 ebus_bus_mmap(t, btype, paddr, flags, hp) 492 bus_space_tag_t t; 493 bus_type_t btype; 494 bus_addr_t paddr; 495 int flags; 496 bus_space_handle_t *hp; 497 { 498 bus_addr_t offset = paddr; 499 struct ebus_softc *sc = t->cookie; 500 int i; 501 502 for (i = 0; i < sc->sc_nrange; i++) { 503 bus_addr_t paddr = ((bus_addr_t)sc->sc_range[i].child_hi << 32) | 504 sc->sc_range[i].child_lo; 505 506 if (offset != paddr) 507 continue; 508 509 DPRINTF(EDB_BUSMAP, ("\n_ebus_bus_mmap: mapping paddr %qx\n", paddr)); 510 return (bus_space_mmap(sc->sc_bustag, 0, paddr, 511 flags, hp)); 512 } 513 514 return (-1); 515 } 516 517 /* 518 * install an interrupt handler for a PCI device 519 */ 520 void * 521 ebus_intr_establish(t, level, flags, handler, arg) 522 bus_space_tag_t t; 523 int level; 524 int flags; 525 int (*handler) __P((void *)); 526 void *arg; 527 { 528 529 /* XXX */ 530 return (0); 531 } 532 533 /* 534 * bus dma support 535 */ 536 int 537 ebus_dmamap_load(t, map, buf, buflen, p, flags) 538 bus_dma_tag_t t; 539 bus_dmamap_t map; 540 void *buf; 541 bus_size_t buflen; 542 struct proc *p; 543 int flags; 544 { 545 struct ebus_softc *sc = t->_cookie; 546 547 return (iommu_dvmamap_load(t, &sc->sc_parent->sc_is, map, buf, buflen, 548 p, flags)); 549 } 550 551 void 552 ebus_dmamap_unload(t, map) 553 bus_dma_tag_t t; 554 bus_dmamap_t map; 555 { 556 struct ebus_softc *sc = t->_cookie; 557 558 iommu_dvmamap_unload(t, &sc->sc_parent->sc_is, map); 559 } 560 561 void 562 ebus_dmamap_sync(t, map, offset, len, ops) 563 bus_dma_tag_t t; 564 bus_dmamap_t map; 565 bus_addr_t offset; 566 bus_size_t len; 567 int ops; 568 { 569 struct ebus_softc *sc = t->_cookie; 570 571 iommu_dvmamap_sync(t, &sc->sc_parent->sc_is, map, offset, len, ops); 572 bus_dmamap_sync(t->_parent, map, offset, len, ops); 573 } 574 575 int 576 ebus_dmamem_alloc(t, size, alignment, boundary, segs, nsegs, rsegs, flags) 577 bus_dma_tag_t t; 578 bus_size_t size; 579 bus_size_t alignment; 580 bus_size_t boundary; 581 bus_dma_segment_t *segs; 582 int nsegs; 583 int *rsegs; 584 int flags; 585 { 586 struct ebus_softc *sc = t->_cookie; 587 588 return (iommu_dvmamem_alloc(t, &sc->sc_parent->sc_is, size, alignment, 589 boundary, segs, nsegs, rsegs, flags)); 590 } 591 592 void 593 ebus_dmamem_free(t, segs, nsegs) 594 bus_dma_tag_t t; 595 bus_dma_segment_t *segs; 596 int nsegs; 597 { 598 struct ebus_softc *sc = t->_cookie; 599 600 iommu_dvmamem_free(t, &sc->sc_parent->sc_is, segs, nsegs); 601 } 602 603 int 604 ebus_dmamem_map(t, segs, nsegs, size, kvap, flags) 605 bus_dma_tag_t t; 606 bus_dma_segment_t *segs; 607 int nsegs; 608 size_t size; 609 caddr_t *kvap; 610 int flags; 611 { 612 struct ebus_softc *sc = t->_cookie; 613 614 return (iommu_dvmamem_map(t, &sc->sc_parent->sc_is, segs, nsegs, 615 size, kvap, flags)); 616 } 617 618 void 619 ebus_dmamem_unmap(t, kva, size) 620 bus_dma_tag_t t; 621 caddr_t kva; 622 size_t size; 623 { 624 struct ebus_softc *sc = t->_cookie; 625 626 iommu_dvmamem_unmap(t, &sc->sc_parent->sc_is, kva, size); 627 } 628