1 /*- 2 * Copyright (c) 1997-2001 Granch, Ltd. All rights reserved. 3 * Author: Denis I.Timofeev <timofeev@granch.ru> 4 * 5 * Redistributon and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 */ 28 29 #include <sys/cdefs.h> 30 __FBSDID("$FreeBSD$"); 31 32 /* 33 * Device driver for Granch SBNI12 leased line adapters 34 * 35 * Revision 2.0.0 1997/08/06 36 * Initial revision by Alexey Zverev 37 * 38 * Revision 2.0.1 1997/08/11 39 * Additional internal statistics support (tx statistics) 40 * 41 * Revision 2.0.2 1997/11/05 42 * if_bpf bug has been fixed 43 * 44 * Revision 2.0.3 1998/12/20 45 * Memory leakage has been eliminated in 46 * the sbni_st and sbni_timeout routines. 47 * 48 * Revision 3.0 2000/08/10 by Yaroslav Polyakov 49 * Support for PCI cards. 4.1 modification. 50 * 51 * Revision 3.1 2000/09/12 52 * Removed extra #defines around bpf functions 53 * 54 * Revision 4.0 2000/11/23 by Denis Timofeev 55 * Completely redesigned the buffer management 56 * 57 * Revision 4.1 2001/01/21 58 * Support for PCI Dual cards and new SBNI12D-10, -11 Dual/ISA cards 59 * 60 * Written with reference to NE2000 driver developed by David Greenman. 61 */ 62 63 64 #include <sys/param.h> 65 #include <sys/systm.h> 66 #include <sys/socket.h> 67 #include <sys/sockio.h> 68 #include <sys/mbuf.h> 69 #include <sys/kernel.h> 70 #include <sys/proc.h> 71 #include <sys/callout.h> 72 #include <sys/syslog.h> 73 #include <sys/random.h> 74 75 #include <machine/bus.h> 76 #include <sys/rman.h> 77 #include <machine/resource.h> 78 79 #include <net/if.h> 80 #include <net/if_dl.h> 81 #include <net/ethernet.h> 82 #include <net/bpf.h> 83 #include <net/if_types.h> 84 85 #include <dev/sbni/if_sbnireg.h> 86 #include <dev/sbni/if_sbnivar.h> 87 88 #define ASM_CRC 1 89 90 static void sbni_init(void *); 91 static void sbni_start(struct ifnet *); 92 static int sbni_ioctl(struct ifnet *, u_long, caddr_t); 93 static void sbni_watchdog(struct ifnet *); 94 static void sbni_stop(struct sbni_softc *); 95 static void handle_channel(struct sbni_softc *); 96 97 static void card_start(struct sbni_softc *); 98 static int recv_frame(struct sbni_softc *); 99 static void send_frame(struct sbni_softc *); 100 static int upload_data(struct sbni_softc *, u_int, u_int, u_int, u_int32_t); 101 static int skip_tail(struct sbni_softc *, u_int, u_int32_t); 102 static void interpret_ack(struct sbni_softc *, u_int); 103 static void download_data(struct sbni_softc *, u_int32_t *); 104 static void prepare_to_send(struct sbni_softc *); 105 static void drop_xmit_queue(struct sbni_softc *); 106 static int get_rx_buf(struct sbni_softc *); 107 static void indicate_pkt(struct sbni_softc *); 108 static void change_level(struct sbni_softc *); 109 static int check_fhdr(struct sbni_softc *, u_int *, u_int *, 110 u_int *, u_int *, u_int32_t *); 111 static int append_frame_to_pkt(struct sbni_softc *, u_int, u_int32_t); 112 static void timeout_change_level(struct sbni_softc *); 113 static void send_frame_header(struct sbni_softc *, u_int32_t *); 114 static void set_initial_values(struct sbni_softc *, struct sbni_flags); 115 116 static u_int32_t calc_crc32(u_int32_t, caddr_t, u_int); 117 static timeout_t sbni_timeout; 118 119 static __inline u_char sbni_inb(struct sbni_softc *, enum sbni_reg); 120 static __inline void sbni_outb(struct sbni_softc *, enum sbni_reg, u_char); 121 static __inline void sbni_insb(struct sbni_softc *, u_char *, u_int); 122 static __inline void sbni_outsb(struct sbni_softc *, u_char *, u_int); 123 124 static u_int32_t crc32tab[]; 125 126 #ifdef SBNI_DUAL_COMPOUND 127 struct sbni_softc *sbni_headlist; 128 #endif 129 130 u_int32_t next_sbni_unit; 131 132 /* -------------------------------------------------------------------------- */ 133 134 static __inline u_char 135 sbni_inb(struct sbni_softc *sc, enum sbni_reg reg) 136 { 137 return bus_space_read_1( 138 rman_get_bustag(sc->io_res), 139 rman_get_bushandle(sc->io_res), 140 sc->io_off + reg); 141 } 142 143 static __inline void 144 sbni_outb(struct sbni_softc *sc, enum sbni_reg reg, u_char value) 145 { 146 bus_space_write_1( 147 rman_get_bustag(sc->io_res), 148 rman_get_bushandle(sc->io_res), 149 sc->io_off + reg, value); 150 } 151 152 static __inline void 153 sbni_insb(struct sbni_softc *sc, u_char *to, u_int len) 154 { 155 bus_space_read_multi_1( 156 rman_get_bustag(sc->io_res), 157 rman_get_bushandle(sc->io_res), 158 sc->io_off + DAT, to, len); 159 } 160 161 static __inline void 162 sbni_outsb(struct sbni_softc *sc, u_char *from, u_int len) 163 { 164 bus_space_write_multi_1( 165 rman_get_bustag(sc->io_res), 166 rman_get_bushandle(sc->io_res), 167 sc->io_off + DAT, from, len); 168 } 169 170 171 /* 172 Valid combinations in CSR0 (for probing): 173 174 VALID_DECODER 0000,0011,1011,1010 175 176 ; 0 ; - 177 TR_REQ ; 1 ; + 178 TR_RDY ; 2 ; - 179 TR_RDY TR_REQ ; 3 ; + 180 BU_EMP ; 4 ; + 181 BU_EMP TR_REQ ; 5 ; + 182 BU_EMP TR_RDY ; 6 ; - 183 BU_EMP TR_RDY TR_REQ ; 7 ; + 184 RC_RDY ; 8 ; + 185 RC_RDY TR_REQ ; 9 ; + 186 RC_RDY TR_RDY ; 10 ; - 187 RC_RDY TR_RDY TR_REQ ; 11 ; - 188 RC_RDY BU_EMP ; 12 ; - 189 RC_RDY BU_EMP TR_REQ ; 13 ; - 190 RC_RDY BU_EMP TR_RDY ; 14 ; - 191 RC_RDY BU_EMP TR_RDY TR_REQ ; 15 ; - 192 */ 193 194 #define VALID_DECODER (2 + 8 + 0x10 + 0x20 + 0x80 + 0x100 + 0x200) 195 196 197 int 198 sbni_probe(struct sbni_softc *sc) 199 { 200 u_char csr0; 201 202 csr0 = sbni_inb(sc, CSR0); 203 if (csr0 != 0xff && csr0 != 0x00) { 204 csr0 &= ~EN_INT; 205 if (csr0 & BU_EMP) 206 csr0 |= EN_INT; 207 208 if (VALID_DECODER & (1 << (csr0 >> 4))) 209 return (0); 210 } 211 212 return (ENXIO); 213 } 214 215 216 /* 217 * Install interface into kernel networking data structures 218 */ 219 void 220 sbni_attach(struct sbni_softc *sc, int unit, struct sbni_flags flags) 221 { 222 struct ifnet *ifp; 223 u_char csr0; 224 225 ifp = sc->ifp = if_alloc(IFT_ETHER); 226 if (ifp == NULL) 227 panic("sbni%d: can not if_alloc()", unit); 228 sbni_outb(sc, CSR0, 0); 229 set_initial_values(sc, flags); 230 231 callout_handle_init(&sc->wch); 232 /* Initialize ifnet structure */ 233 ifp->if_softc = sc; 234 if_initname(ifp, "sbni", unit); 235 ifp->if_init = sbni_init; 236 ifp->if_start = sbni_start; 237 ifp->if_ioctl = sbni_ioctl; 238 ifp->if_watchdog = sbni_watchdog; 239 ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; 240 241 /* report real baud rate */ 242 csr0 = sbni_inb(sc, CSR0); 243 ifp->if_baudrate = 244 (csr0 & 0x01 ? 500000 : 2000000) / (1 << flags.rate); 245 246 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST | 247 IFF_NEEDSGIANT; 248 ether_ifattach(ifp, sc->enaddr); 249 /* device attach does transition from UNCONFIGURED to IDLE state */ 250 251 if_printf(ifp, "speed %ld, rxl ", ifp->if_baudrate); 252 if (sc->delta_rxl) 253 printf("auto\n"); 254 else 255 printf("%d (fixed)\n", sc->cur_rxl_index); 256 } 257 258 /* -------------------------------------------------------------------------- */ 259 260 static void 261 sbni_init(void *xsc) 262 { 263 struct sbni_softc *sc; 264 struct ifnet *ifp; 265 int s; 266 267 sc = (struct sbni_softc *)xsc; 268 ifp = sc->ifp; 269 270 /* 271 * kludge to avoid multiple initialization when more than once 272 * protocols configured 273 */ 274 if (ifp->if_drv_flags & IFF_DRV_RUNNING) 275 return; 276 277 s = splimp(); 278 ifp->if_timer = 0; 279 card_start(sc); 280 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ); 281 282 ifp->if_drv_flags |= IFF_DRV_RUNNING; 283 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 284 285 /* attempt to start output */ 286 sbni_start(ifp); 287 splx(s); 288 } 289 290 291 static void 292 sbni_start(struct ifnet *ifp) 293 { 294 struct sbni_softc *sc = ifp->if_softc; 295 if (sc->tx_frameno == 0) 296 prepare_to_send(sc); 297 } 298 299 300 static void 301 sbni_stop(struct sbni_softc *sc) 302 { 303 sbni_outb(sc, CSR0, 0); 304 drop_xmit_queue(sc); 305 306 if (sc->rx_buf_p) { 307 m_freem(sc->rx_buf_p); 308 sc->rx_buf_p = NULL; 309 } 310 311 untimeout(sbni_timeout, sc, sc->wch); 312 sc->wch.callout = NULL; 313 } 314 315 /* -------------------------------------------------------------------------- */ 316 317 /* interrupt handler */ 318 319 /* 320 * SBNI12D-10, -11/ISA boards within "common interrupt" mode could not 321 * be looked as two independent single-channel devices. Every channel seems 322 * as Ethernet interface but interrupt handler must be common. Really, first 323 * channel ("master") driver only registers the handler. In it's struct softc 324 * it has got pointer to "slave" channel's struct softc and handles that's 325 * interrupts too. 326 * softc of successfully attached ISA SBNI boards is linked to list. 327 * While next board driver is initialized, it scans this list. If one 328 * has found softc with same irq and ioaddr different by 4 then it assumes 329 * this board to be "master". 330 */ 331 332 void 333 sbni_intr(void *arg) 334 { 335 struct sbni_softc *sc; 336 int repeat; 337 338 sc = (struct sbni_softc *)arg; 339 340 do { 341 repeat = 0; 342 if (sbni_inb(sc, CSR0) & (RC_RDY | TR_RDY)) { 343 handle_channel(sc); 344 repeat = 1; 345 } 346 if (sc->slave_sc && /* second channel present */ 347 (sbni_inb(sc->slave_sc, CSR0) & (RC_RDY | TR_RDY))) { 348 handle_channel(sc->slave_sc); 349 repeat = 1; 350 } 351 } while (repeat); 352 } 353 354 355 static void 356 handle_channel(struct sbni_softc *sc) 357 { 358 int req_ans; 359 u_char csr0; 360 361 sbni_outb(sc, CSR0, (sbni_inb(sc, CSR0) & ~EN_INT) | TR_REQ); 362 363 sc->timer_ticks = CHANGE_LEVEL_START_TICKS; 364 for (;;) { 365 csr0 = sbni_inb(sc, CSR0); 366 if ((csr0 & (RC_RDY | TR_RDY)) == 0) 367 break; 368 369 req_ans = !(sc->state & FL_PREV_OK); 370 371 if (csr0 & RC_RDY) 372 req_ans = recv_frame(sc); 373 374 /* 375 * TR_RDY always equals 1 here because we have owned the marker, 376 * and we set TR_REQ when disabled interrupts 377 */ 378 csr0 = sbni_inb(sc, CSR0); 379 if ((csr0 & TR_RDY) == 0 || (csr0 & RC_RDY) != 0) 380 printf("sbni: internal error!\n"); 381 382 /* if state & FL_NEED_RESEND != 0 then tx_frameno != 0 */ 383 if (req_ans || sc->tx_frameno != 0) 384 send_frame(sc); 385 else { 386 /* send the marker without any data */ 387 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) & ~TR_REQ); 388 } 389 } 390 391 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | EN_INT); 392 } 393 394 395 /* 396 * Routine returns 1 if it need to acknoweledge received frame. 397 * Empty frame received without errors won't be acknoweledged. 398 */ 399 400 static int 401 recv_frame(struct sbni_softc *sc) 402 { 403 u_int32_t crc; 404 u_int framelen, frameno, ack; 405 u_int is_first, frame_ok; 406 407 crc = CRC32_INITIAL; 408 if (check_fhdr(sc, &framelen, &frameno, &ack, &is_first, &crc)) { 409 frame_ok = framelen > 4 ? 410 upload_data(sc, framelen, frameno, is_first, crc) : 411 skip_tail(sc, framelen, crc); 412 if (frame_ok) 413 interpret_ack(sc, ack); 414 } else 415 frame_ok = 0; 416 417 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) ^ CT_ZER); 418 if (frame_ok) { 419 sc->state |= FL_PREV_OK; 420 if (framelen > 4) 421 sc->in_stats.all_rx_number++; 422 } else { 423 sc->state &= ~FL_PREV_OK; 424 change_level(sc); 425 sc->in_stats.all_rx_number++; 426 sc->in_stats.bad_rx_number++; 427 } 428 429 return (!frame_ok || framelen > 4); 430 } 431 432 433 static void 434 send_frame(struct sbni_softc *sc) 435 { 436 u_int32_t crc; 437 u_char csr0; 438 439 crc = CRC32_INITIAL; 440 if (sc->state & FL_NEED_RESEND) { 441 442 /* if frame was sended but not ACK'ed - resend it */ 443 if (sc->trans_errors) { 444 sc->trans_errors--; 445 if (sc->framelen != 0) 446 sc->in_stats.resend_tx_number++; 447 } else { 448 /* cannot xmit with many attempts */ 449 drop_xmit_queue(sc); 450 goto do_send; 451 } 452 } else 453 sc->trans_errors = TR_ERROR_COUNT; 454 455 send_frame_header(sc, &crc); 456 sc->state |= FL_NEED_RESEND; 457 /* 458 * FL_NEED_RESEND will be cleared after ACK, but if empty 459 * frame sended then in prepare_to_send next frame 460 */ 461 462 463 if (sc->framelen) { 464 download_data(sc, &crc); 465 sc->in_stats.all_tx_number++; 466 sc->state |= FL_WAIT_ACK; 467 } 468 469 sbni_outsb(sc, (u_char *)&crc, sizeof crc); 470 471 do_send: 472 csr0 = sbni_inb(sc, CSR0); 473 sbni_outb(sc, CSR0, csr0 & ~TR_REQ); 474 475 if (sc->tx_frameno) { 476 /* next frame exists - request to send */ 477 sbni_outb(sc, CSR0, csr0 | TR_REQ); 478 } 479 } 480 481 482 static void 483 download_data(struct sbni_softc *sc, u_int32_t *crc_p) 484 { 485 struct mbuf *m; 486 caddr_t data_p; 487 u_int data_len, pos, slice; 488 489 data_p = NULL; /* initialized to avoid warn */ 490 pos = 0; 491 492 for (m = sc->tx_buf_p; m != NULL && pos < sc->pktlen; m = m->m_next) { 493 if (pos + m->m_len > sc->outpos) { 494 data_len = m->m_len - (sc->outpos - pos); 495 data_p = mtod(m, caddr_t) + (sc->outpos - pos); 496 497 goto do_copy; 498 } else 499 pos += m->m_len; 500 } 501 502 data_len = 0; 503 504 do_copy: 505 pos = 0; 506 do { 507 if (data_len) { 508 slice = min(data_len, sc->framelen - pos); 509 sbni_outsb(sc, data_p, slice); 510 *crc_p = calc_crc32(*crc_p, data_p, slice); 511 512 pos += slice; 513 if (data_len -= slice) 514 data_p += slice; 515 else { 516 do { 517 m = m->m_next; 518 } while (m != NULL && m->m_len == 0); 519 520 if (m) { 521 data_len = m->m_len; 522 data_p = mtod(m, caddr_t); 523 } 524 } 525 } else { 526 /* frame too short - zero padding */ 527 528 pos = sc->framelen - pos; 529 while (pos--) { 530 sbni_outb(sc, DAT, 0); 531 *crc_p = CRC32(0, *crc_p); 532 } 533 return; 534 } 535 } while (pos < sc->framelen); 536 } 537 538 539 static int 540 upload_data(struct sbni_softc *sc, u_int framelen, u_int frameno, 541 u_int is_first, u_int32_t crc) 542 { 543 int frame_ok; 544 545 if (is_first) { 546 sc->wait_frameno = frameno; 547 sc->inppos = 0; 548 } 549 550 if (sc->wait_frameno == frameno) { 551 552 if (sc->inppos + framelen <= ETHER_MAX_LEN) { 553 frame_ok = append_frame_to_pkt(sc, framelen, crc); 554 555 /* 556 * if CRC is right but framelen incorrect then transmitter 557 * error was occured... drop entire packet 558 */ 559 } else if ((frame_ok = skip_tail(sc, framelen, crc)) != 0) { 560 sc->wait_frameno = 0; 561 sc->inppos = 0; 562 sc->ifp->if_ierrors++; 563 /* now skip all frames until is_first != 0 */ 564 } 565 } else 566 frame_ok = skip_tail(sc, framelen, crc); 567 568 if (is_first && !frame_ok) { 569 /* 570 * Frame has been violated, but we have stored 571 * is_first already... Drop entire packet. 572 */ 573 sc->wait_frameno = 0; 574 sc->ifp->if_ierrors++; 575 } 576 577 return (frame_ok); 578 } 579 580 581 static __inline void send_complete(struct sbni_softc *); 582 583 static __inline void 584 send_complete(struct sbni_softc *sc) 585 { 586 m_freem(sc->tx_buf_p); 587 sc->tx_buf_p = NULL; 588 sc->ifp->if_opackets++; 589 } 590 591 592 static void 593 interpret_ack(struct sbni_softc *sc, u_int ack) 594 { 595 if (ack == FRAME_SENT_OK) { 596 sc->state &= ~FL_NEED_RESEND; 597 598 if (sc->state & FL_WAIT_ACK) { 599 sc->outpos += sc->framelen; 600 601 if (--sc->tx_frameno) { 602 sc->framelen = min( 603 sc->maxframe, sc->pktlen - sc->outpos); 604 } else { 605 send_complete(sc); 606 prepare_to_send(sc); 607 } 608 } 609 } 610 611 sc->state &= ~FL_WAIT_ACK; 612 } 613 614 615 /* 616 * Glue received frame with previous fragments of packet. 617 * Indicate packet when last frame would be accepted. 618 */ 619 620 static int 621 append_frame_to_pkt(struct sbni_softc *sc, u_int framelen, u_int32_t crc) 622 { 623 caddr_t p; 624 625 if (sc->inppos + framelen > ETHER_MAX_LEN) 626 return (0); 627 628 if (!sc->rx_buf_p && !get_rx_buf(sc)) 629 return (0); 630 631 p = sc->rx_buf_p->m_data + sc->inppos; 632 sbni_insb(sc, p, framelen); 633 if (calc_crc32(crc, p, framelen) != CRC32_REMAINDER) 634 return (0); 635 636 sc->inppos += framelen - 4; 637 if (--sc->wait_frameno == 0) { /* last frame received */ 638 indicate_pkt(sc); 639 sc->ifp->if_ipackets++; 640 } 641 642 return (1); 643 } 644 645 646 /* 647 * Prepare to start output on adapter. Current priority must be set to splimp 648 * before this routine is called. 649 * Transmitter will be actually activated when marker has been accepted. 650 */ 651 652 static void 653 prepare_to_send(struct sbni_softc *sc) 654 { 655 struct mbuf *m; 656 u_int len; 657 658 /* sc->tx_buf_p == NULL here! */ 659 if (sc->tx_buf_p) 660 printf("sbni: memory leak!\n"); 661 662 sc->outpos = 0; 663 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND); 664 665 for (;;) { 666 IF_DEQUEUE(&sc->ifp->if_snd, sc->tx_buf_p); 667 if (!sc->tx_buf_p) { 668 /* nothing to transmit... */ 669 sc->pktlen = 0; 670 sc->tx_frameno = 0; 671 sc->framelen = 0; 672 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 673 return; 674 } 675 676 for (len = 0, m = sc->tx_buf_p; m; m = m->m_next) 677 len += m->m_len; 678 679 if (len != 0) 680 break; 681 m_freem(sc->tx_buf_p); 682 } 683 684 if (len < SBNI_MIN_LEN) 685 len = SBNI_MIN_LEN; 686 687 sc->pktlen = len; 688 sc->tx_frameno = (len + sc->maxframe - 1) / sc->maxframe; 689 sc->framelen = min(len, sc->maxframe); 690 691 sbni_outb(sc, CSR0, sbni_inb(sc, CSR0) | TR_REQ); 692 sc->ifp->if_drv_flags |= IFF_DRV_OACTIVE; 693 BPF_MTAP(sc->ifp, sc->tx_buf_p); 694 } 695 696 697 static void 698 drop_xmit_queue(struct sbni_softc *sc) 699 { 700 struct mbuf *m; 701 702 if (sc->tx_buf_p) { 703 m_freem(sc->tx_buf_p); 704 sc->tx_buf_p = NULL; 705 sc->ifp->if_oerrors++; 706 } 707 708 for (;;) { 709 IF_DEQUEUE(&sc->ifp->if_snd, m); 710 if (m == NULL) 711 break; 712 m_freem(m); 713 sc->ifp->if_oerrors++; 714 } 715 716 sc->tx_frameno = 0; 717 sc->framelen = 0; 718 sc->outpos = 0; 719 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND); 720 sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 721 } 722 723 724 static void 725 send_frame_header(struct sbni_softc *sc, u_int32_t *crc_p) 726 { 727 u_int32_t crc; 728 u_int len_field; 729 u_char value; 730 731 crc = *crc_p; 732 len_field = sc->framelen + 6; /* CRC + frameno + reserved */ 733 734 if (sc->state & FL_NEED_RESEND) 735 len_field |= FRAME_RETRY; /* non-first attempt... */ 736 737 if (sc->outpos == 0) 738 len_field |= FRAME_FIRST; 739 740 len_field |= (sc->state & FL_PREV_OK) ? FRAME_SENT_OK : FRAME_SENT_BAD; 741 sbni_outb(sc, DAT, SBNI_SIG); 742 743 value = (u_char)len_field; 744 sbni_outb(sc, DAT, value); 745 crc = CRC32(value, crc); 746 value = (u_char)(len_field >> 8); 747 sbni_outb(sc, DAT, value); 748 crc = CRC32(value, crc); 749 750 sbni_outb(sc, DAT, sc->tx_frameno); 751 crc = CRC32(sc->tx_frameno, crc); 752 sbni_outb(sc, DAT, 0); 753 crc = CRC32(0, crc); 754 *crc_p = crc; 755 } 756 757 758 /* 759 * if frame tail not needed (incorrect number or received twice), 760 * it won't store, but CRC will be calculated 761 */ 762 763 static int 764 skip_tail(struct sbni_softc *sc, u_int tail_len, u_int32_t crc) 765 { 766 while (tail_len--) 767 crc = CRC32(sbni_inb(sc, DAT), crc); 768 769 return (crc == CRC32_REMAINDER); 770 } 771 772 773 static int 774 check_fhdr(struct sbni_softc *sc, u_int *framelen, u_int *frameno, 775 u_int *ack, u_int *is_first, u_int32_t *crc_p) 776 { 777 u_int32_t crc; 778 u_char value; 779 780 crc = *crc_p; 781 if (sbni_inb(sc, DAT) != SBNI_SIG) 782 return (0); 783 784 value = sbni_inb(sc, DAT); 785 *framelen = (u_int)value; 786 crc = CRC32(value, crc); 787 value = sbni_inb(sc, DAT); 788 *framelen |= ((u_int)value) << 8; 789 crc = CRC32(value, crc); 790 791 *ack = *framelen & FRAME_ACK_MASK; 792 *is_first = (*framelen & FRAME_FIRST) != 0; 793 794 if ((*framelen &= FRAME_LEN_MASK) < 6 || *framelen > SBNI_MAX_FRAME - 3) 795 return (0); 796 797 value = sbni_inb(sc, DAT); 798 *frameno = (u_int)value; 799 crc = CRC32(value, crc); 800 801 crc = CRC32(sbni_inb(sc, DAT), crc); /* reserved byte */ 802 *framelen -= 2; 803 804 *crc_p = crc; 805 return (1); 806 } 807 808 809 static int 810 get_rx_buf(struct sbni_softc *sc) 811 { 812 struct mbuf *m; 813 814 MGETHDR(m, M_DONTWAIT, MT_DATA); 815 if (m == NULL) { 816 if_printf(sc->ifp, "cannot allocate header mbuf\n"); 817 return (0); 818 } 819 820 /* 821 * We always put the received packet in a single buffer - 822 * either with just an mbuf header or in a cluster attached 823 * to the header. The +2 is to compensate for the alignment 824 * fixup below. 825 */ 826 if (ETHER_MAX_LEN + 2 > MHLEN) { 827 /* Attach an mbuf cluster */ 828 MCLGET(m, M_DONTWAIT); 829 if ((m->m_flags & M_EXT) == 0) { 830 m_freem(m); 831 return (0); 832 } 833 } 834 m->m_pkthdr.len = m->m_len = ETHER_MAX_LEN + 2; 835 836 /* 837 * The +2 is to longword align the start of the real packet. 838 * (sizeof ether_header == 14) 839 * This is important for NFS. 840 */ 841 m_adj(m, 2); 842 sc->rx_buf_p = m; 843 return (1); 844 } 845 846 847 static void 848 indicate_pkt(struct sbni_softc *sc) 849 { 850 struct ifnet *ifp = sc->ifp; 851 struct mbuf *m; 852 853 m = sc->rx_buf_p; 854 m->m_pkthdr.rcvif = ifp; 855 m->m_pkthdr.len = m->m_len = sc->inppos; 856 857 (*ifp->if_input)(ifp, m); 858 sc->rx_buf_p = NULL; 859 } 860 861 /* -------------------------------------------------------------------------- */ 862 863 /* 864 * Routine checks periodically wire activity and regenerates marker if 865 * connect was inactive for a long time. 866 */ 867 868 static void 869 sbni_timeout(void *xsc) 870 { 871 struct sbni_softc *sc; 872 int s; 873 u_char csr0; 874 875 sc = (struct sbni_softc *)xsc; 876 s = splimp(); 877 878 csr0 = sbni_inb(sc, CSR0); 879 if (csr0 & RC_CHK) { 880 881 if (sc->timer_ticks) { 882 if (csr0 & (RC_RDY | BU_EMP)) 883 /* receiving not active */ 884 sc->timer_ticks--; 885 } else { 886 sc->in_stats.timeout_number++; 887 if (sc->delta_rxl) 888 timeout_change_level(sc); 889 890 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES); 891 csr0 = sbni_inb(sc, CSR0); 892 } 893 } 894 895 sbni_outb(sc, CSR0, csr0 | RC_CHK); 896 sc->wch = timeout(sbni_timeout, sc, hz/SBNI_HZ); 897 splx(s); 898 } 899 900 /* -------------------------------------------------------------------------- */ 901 902 static void 903 card_start(struct sbni_softc *sc) 904 { 905 sc->timer_ticks = CHANGE_LEVEL_START_TICKS; 906 sc->state &= ~(FL_WAIT_ACK | FL_NEED_RESEND); 907 sc->state |= FL_PREV_OK; 908 909 sc->inppos = 0; 910 sc->wait_frameno = 0; 911 912 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1 | PR_RES); 913 sbni_outb(sc, CSR0, EN_INT); 914 } 915 916 /* -------------------------------------------------------------------------- */ 917 918 /* 919 * Device timeout/watchdog routine. Entered if the device neglects to 920 * generate an interrupt after a transmit has been started on it. 921 */ 922 923 static void 924 sbni_watchdog(struct ifnet *ifp) 925 { 926 log(LOG_ERR, "%s: device timeout\n", ifp->if_xname); 927 ifp->if_oerrors++; 928 } 929 930 931 static u_char rxl_tab[] = { 932 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, 933 0x0a, 0x0c, 0x0f, 0x16, 0x18, 0x1a, 0x1c, 0x1f 934 }; 935 936 #define SIZE_OF_TIMEOUT_RXL_TAB 4 937 static u_char timeout_rxl_tab[] = { 938 0x03, 0x05, 0x08, 0x0b 939 }; 940 941 static void 942 set_initial_values(struct sbni_softc *sc, struct sbni_flags flags) 943 { 944 if (flags.fixed_rxl) { 945 sc->delta_rxl = 0; /* disable receive level autodetection */ 946 sc->cur_rxl_index = flags.rxl; 947 } else { 948 sc->delta_rxl = DEF_RXL_DELTA; 949 sc->cur_rxl_index = DEF_RXL; 950 } 951 952 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE; 953 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index]; 954 sc->maxframe = DEFAULT_FRAME_LEN; 955 956 /* 957 * generate Ethernet address (0x00ff01xxxxxx) 958 */ 959 *(u_int16_t *) sc->enaddr = htons(0x00ff); 960 if (flags.mac_addr) { 961 *(u_int32_t *) (sc->enaddr + 2) = 962 htonl(flags.mac_addr | 0x01000000); 963 } else { 964 *(u_char *) (sc->enaddr + 2) = 0x01; 965 read_random(sc->enaddr + 3, 3); 966 } 967 } 968 969 970 #ifdef SBNI_DUAL_COMPOUND 971 972 struct sbni_softc * 973 connect_to_master(struct sbni_softc *sc) 974 { 975 struct sbni_softc *p, *p_prev; 976 977 for (p = sbni_headlist, p_prev = NULL; p; p_prev = p, p = p->link) { 978 if (rman_get_start(p->io_res) == rman_get_start(sc->io_res) + 4 || 979 rman_get_start(p->io_res) == rman_get_start(sc->io_res) - 4) { 980 p->slave_sc = sc; 981 if (p_prev) 982 p_prev->link = p->link; 983 else 984 sbni_headlist = p->link; 985 return p; 986 } 987 } 988 989 return (NULL); 990 } 991 992 #endif /* SBNI_DUAL_COMPOUND */ 993 994 995 /* Receive level auto-selection */ 996 997 static void 998 change_level(struct sbni_softc *sc) 999 { 1000 if (sc->delta_rxl == 0) /* do not auto-negotiate RxL */ 1001 return; 1002 1003 if (sc->cur_rxl_index == 0) 1004 sc->delta_rxl = 1; 1005 else if (sc->cur_rxl_index == 15) 1006 sc->delta_rxl = -1; 1007 else if (sc->cur_rxl_rcvd < sc->prev_rxl_rcvd) 1008 sc->delta_rxl = -sc->delta_rxl; 1009 1010 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index += sc->delta_rxl]; 1011 sbni_inb(sc, CSR0); /* it needed for PCI cards */ 1012 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1); 1013 1014 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd; 1015 sc->cur_rxl_rcvd = 0; 1016 } 1017 1018 1019 static void 1020 timeout_change_level(struct sbni_softc *sc) 1021 { 1022 sc->cur_rxl_index = timeout_rxl_tab[sc->timeout_rxl]; 1023 if (++sc->timeout_rxl >= 4) 1024 sc->timeout_rxl = 0; 1025 1026 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index]; 1027 sbni_inb(sc, CSR0); 1028 sbni_outb(sc, CSR1, *(u_char *)&sc->csr1); 1029 1030 sc->prev_rxl_rcvd = sc->cur_rxl_rcvd; 1031 sc->cur_rxl_rcvd = 0; 1032 } 1033 1034 /* -------------------------------------------------------------------------- */ 1035 1036 /* 1037 * Process an ioctl request. This code needs some work - it looks 1038 * pretty ugly. 1039 */ 1040 1041 static int 1042 sbni_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 1043 { 1044 struct sbni_softc *sc; 1045 struct ifreq *ifr; 1046 struct thread *td; 1047 struct sbni_in_stats *in_stats; 1048 struct sbni_flags flags; 1049 int error, s; 1050 1051 sc = ifp->if_softc; 1052 ifr = (struct ifreq *)data; 1053 td = curthread; 1054 error = 0; 1055 1056 s = splimp(); 1057 1058 switch (command) { 1059 case SIOCSIFFLAGS: 1060 /* 1061 * If the interface is marked up and stopped, then start it. 1062 * If it is marked down and running, then stop it. 1063 */ 1064 if (ifp->if_flags & IFF_UP) { 1065 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) 1066 sbni_init(sc); 1067 } else { 1068 if (ifp->if_drv_flags & IFF_DRV_RUNNING) { 1069 sbni_stop(sc); 1070 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 1071 } 1072 } 1073 break; 1074 1075 case SIOCADDMULTI: 1076 case SIOCDELMULTI: 1077 /* 1078 * Multicast list has changed; set the hardware filter 1079 * accordingly. 1080 */ 1081 error = 0; 1082 /* if (ifr == NULL) 1083 error = EAFNOSUPPORT; */ 1084 break; 1085 1086 case SIOCSIFMTU: 1087 if (ifr->ifr_mtu > ETHERMTU) 1088 error = EINVAL; 1089 else 1090 ifp->if_mtu = ifr->ifr_mtu; 1091 break; 1092 1093 /* 1094 * SBNI specific ioctl 1095 */ 1096 case SIOCGHWFLAGS: /* get flags */ 1097 bcopy((caddr_t)IF_LLADDR(sc->ifp)+3, (caddr_t) &flags, 3); 1098 flags.rxl = sc->cur_rxl_index; 1099 flags.rate = sc->csr1.rate; 1100 flags.fixed_rxl = (sc->delta_rxl == 0); 1101 flags.fixed_rate = 1; 1102 ifr->ifr_data = *(caddr_t*) &flags; 1103 break; 1104 1105 case SIOCGINSTATS: 1106 in_stats = (struct sbni_in_stats *)ifr->ifr_data; 1107 bcopy((void *)(&(sc->in_stats)), (void *)in_stats, 1108 sizeof(struct sbni_in_stats)); 1109 break; 1110 1111 case SIOCSHWFLAGS: /* set flags */ 1112 /* root only */ 1113 error = suser(td); 1114 if (error) 1115 break; 1116 flags = *(struct sbni_flags*)&ifr->ifr_data; 1117 if (flags.fixed_rxl) { 1118 sc->delta_rxl = 0; 1119 sc->cur_rxl_index = flags.rxl; 1120 } else { 1121 sc->delta_rxl = DEF_RXL_DELTA; 1122 sc->cur_rxl_index = DEF_RXL; 1123 } 1124 sc->csr1.rxl = rxl_tab[sc->cur_rxl_index]; 1125 sc->csr1.rate = flags.fixed_rate ? flags.rate : DEFAULT_RATE; 1126 if (flags.mac_addr) 1127 bcopy((caddr_t) &flags, 1128 (caddr_t) IF_LLADDR(sc->ifp)+3, 3); 1129 1130 /* Don't be afraid... */ 1131 sbni_outb(sc, CSR1, *(char*)(&sc->csr1) | PR_RES); 1132 break; 1133 1134 case SIOCRINSTATS: 1135 if (!(error = suser(td))) /* root only */ 1136 bzero(&sc->in_stats, sizeof(struct sbni_in_stats)); 1137 break; 1138 1139 default: 1140 error = ether_ioctl(ifp, command, data); 1141 break; 1142 } 1143 1144 splx(s); 1145 return (error); 1146 } 1147 1148 /* -------------------------------------------------------------------------- */ 1149 1150 #ifdef ASM_CRC 1151 1152 static u_int32_t 1153 calc_crc32(u_int32_t crc, caddr_t p, u_int len) 1154 { 1155 register u_int32_t _crc __asm ("ax"); 1156 _crc = crc; 1157 1158 __asm __volatile ( 1159 "xorl %%ebx, %%ebx\n" 1160 "movl %1, %%esi\n" 1161 "movl %2, %%ecx\n" 1162 "movl $crc32tab, %%edi\n" 1163 "shrl $2, %%ecx\n" 1164 "jz 1f\n" 1165 1166 ".align 4\n" 1167 "0:\n" 1168 "movb %%al, %%bl\n" 1169 "movl (%%esi), %%edx\n" 1170 "shrl $8, %%eax\n" 1171 "xorb %%dl, %%bl\n" 1172 "shrl $8, %%edx\n" 1173 "xorl (%%edi,%%ebx,4), %%eax\n" 1174 1175 "movb %%al, %%bl\n" 1176 "shrl $8, %%eax\n" 1177 "xorb %%dl, %%bl\n" 1178 "shrl $8, %%edx\n" 1179 "xorl (%%edi,%%ebx,4), %%eax\n" 1180 1181 "movb %%al, %%bl\n" 1182 "shrl $8, %%eax\n" 1183 "xorb %%dl, %%bl\n" 1184 "movb %%dh, %%dl\n" 1185 "xorl (%%edi,%%ebx,4), %%eax\n" 1186 1187 "movb %%al, %%bl\n" 1188 "shrl $8, %%eax\n" 1189 "xorb %%dl, %%bl\n" 1190 "addl $4, %%esi\n" 1191 "xorl (%%edi,%%ebx,4), %%eax\n" 1192 1193 "decl %%ecx\n" 1194 "jnz 0b\n" 1195 1196 "1:\n" 1197 "movl %2, %%ecx\n" 1198 "andl $3, %%ecx\n" 1199 "jz 2f\n" 1200 1201 "movb %%al, %%bl\n" 1202 "shrl $8, %%eax\n" 1203 "xorb (%%esi), %%bl\n" 1204 "xorl (%%edi,%%ebx,4), %%eax\n" 1205 1206 "decl %%ecx\n" 1207 "jz 2f\n" 1208 1209 "movb %%al, %%bl\n" 1210 "shrl $8, %%eax\n" 1211 "xorb 1(%%esi), %%bl\n" 1212 "xorl (%%edi,%%ebx,4), %%eax\n" 1213 1214 "decl %%ecx\n" 1215 "jz 2f\n" 1216 1217 "movb %%al, %%bl\n" 1218 "shrl $8, %%eax\n" 1219 "xorb 2(%%esi), %%bl\n" 1220 "xorl (%%edi,%%ebx,4), %%eax\n" 1221 "2:\n" 1222 : "=a" (_crc) 1223 : "g" (p), "g" (len) 1224 : "bx", "cx", "dx", "si", "di" 1225 ); 1226 1227 return (_crc); 1228 } 1229 1230 #else /* ASM_CRC */ 1231 1232 static u_int32_t 1233 calc_crc32(u_int32_t crc, caddr_t p, u_int len) 1234 { 1235 while (len--) 1236 crc = CRC32(*p++, crc); 1237 1238 return (crc); 1239 } 1240 1241 #endif /* ASM_CRC */ 1242 1243 1244 static u_int32_t crc32tab[] __aligned(8) = { 1245 0xD202EF8D, 0xA505DF1B, 0x3C0C8EA1, 0x4B0BBE37, 1246 0xD56F2B94, 0xA2681B02, 0x3B614AB8, 0x4C667A2E, 1247 0xDCD967BF, 0xABDE5729, 0x32D70693, 0x45D03605, 1248 0xDBB4A3A6, 0xACB39330, 0x35BAC28A, 0x42BDF21C, 1249 0xCFB5FFE9, 0xB8B2CF7F, 0x21BB9EC5, 0x56BCAE53, 1250 0xC8D83BF0, 0xBFDF0B66, 0x26D65ADC, 0x51D16A4A, 1251 0xC16E77DB, 0xB669474D, 0x2F6016F7, 0x58672661, 1252 0xC603B3C2, 0xB1048354, 0x280DD2EE, 0x5F0AE278, 1253 0xE96CCF45, 0x9E6BFFD3, 0x0762AE69, 0x70659EFF, 1254 0xEE010B5C, 0x99063BCA, 0x000F6A70, 0x77085AE6, 1255 0xE7B74777, 0x90B077E1, 0x09B9265B, 0x7EBE16CD, 1256 0xE0DA836E, 0x97DDB3F8, 0x0ED4E242, 0x79D3D2D4, 1257 0xF4DBDF21, 0x83DCEFB7, 0x1AD5BE0D, 0x6DD28E9B, 1258 0xF3B61B38, 0x84B12BAE, 0x1DB87A14, 0x6ABF4A82, 1259 0xFA005713, 0x8D076785, 0x140E363F, 0x630906A9, 1260 0xFD6D930A, 0x8A6AA39C, 0x1363F226, 0x6464C2B0, 1261 0xA4DEAE1D, 0xD3D99E8B, 0x4AD0CF31, 0x3DD7FFA7, 1262 0xA3B36A04, 0xD4B45A92, 0x4DBD0B28, 0x3ABA3BBE, 1263 0xAA05262F, 0xDD0216B9, 0x440B4703, 0x330C7795, 1264 0xAD68E236, 0xDA6FD2A0, 0x4366831A, 0x3461B38C, 1265 0xB969BE79, 0xCE6E8EEF, 0x5767DF55, 0x2060EFC3, 1266 0xBE047A60, 0xC9034AF6, 0x500A1B4C, 0x270D2BDA, 1267 0xB7B2364B, 0xC0B506DD, 0x59BC5767, 0x2EBB67F1, 1268 0xB0DFF252, 0xC7D8C2C4, 0x5ED1937E, 0x29D6A3E8, 1269 0x9FB08ED5, 0xE8B7BE43, 0x71BEEFF9, 0x06B9DF6F, 1270 0x98DD4ACC, 0xEFDA7A5A, 0x76D32BE0, 0x01D41B76, 1271 0x916B06E7, 0xE66C3671, 0x7F6567CB, 0x0862575D, 1272 0x9606C2FE, 0xE101F268, 0x7808A3D2, 0x0F0F9344, 1273 0x82079EB1, 0xF500AE27, 0x6C09FF9D, 0x1B0ECF0B, 1274 0x856A5AA8, 0xF26D6A3E, 0x6B643B84, 0x1C630B12, 1275 0x8CDC1683, 0xFBDB2615, 0x62D277AF, 0x15D54739, 1276 0x8BB1D29A, 0xFCB6E20C, 0x65BFB3B6, 0x12B88320, 1277 0x3FBA6CAD, 0x48BD5C3B, 0xD1B40D81, 0xA6B33D17, 1278 0x38D7A8B4, 0x4FD09822, 0xD6D9C998, 0xA1DEF90E, 1279 0x3161E49F, 0x4666D409, 0xDF6F85B3, 0xA868B525, 1280 0x360C2086, 0x410B1010, 0xD80241AA, 0xAF05713C, 1281 0x220D7CC9, 0x550A4C5F, 0xCC031DE5, 0xBB042D73, 1282 0x2560B8D0, 0x52678846, 0xCB6ED9FC, 0xBC69E96A, 1283 0x2CD6F4FB, 0x5BD1C46D, 0xC2D895D7, 0xB5DFA541, 1284 0x2BBB30E2, 0x5CBC0074, 0xC5B551CE, 0xB2B26158, 1285 0x04D44C65, 0x73D37CF3, 0xEADA2D49, 0x9DDD1DDF, 1286 0x03B9887C, 0x74BEB8EA, 0xEDB7E950, 0x9AB0D9C6, 1287 0x0A0FC457, 0x7D08F4C1, 0xE401A57B, 0x930695ED, 1288 0x0D62004E, 0x7A6530D8, 0xE36C6162, 0x946B51F4, 1289 0x19635C01, 0x6E646C97, 0xF76D3D2D, 0x806A0DBB, 1290 0x1E0E9818, 0x6909A88E, 0xF000F934, 0x8707C9A2, 1291 0x17B8D433, 0x60BFE4A5, 0xF9B6B51F, 0x8EB18589, 1292 0x10D5102A, 0x67D220BC, 0xFEDB7106, 0x89DC4190, 1293 0x49662D3D, 0x3E611DAB, 0xA7684C11, 0xD06F7C87, 1294 0x4E0BE924, 0x390CD9B2, 0xA0058808, 0xD702B89E, 1295 0x47BDA50F, 0x30BA9599, 0xA9B3C423, 0xDEB4F4B5, 1296 0x40D06116, 0x37D75180, 0xAEDE003A, 0xD9D930AC, 1297 0x54D13D59, 0x23D60DCF, 0xBADF5C75, 0xCDD86CE3, 1298 0x53BCF940, 0x24BBC9D6, 0xBDB2986C, 0xCAB5A8FA, 1299 0x5A0AB56B, 0x2D0D85FD, 0xB404D447, 0xC303E4D1, 1300 0x5D677172, 0x2A6041E4, 0xB369105E, 0xC46E20C8, 1301 0x72080DF5, 0x050F3D63, 0x9C066CD9, 0xEB015C4F, 1302 0x7565C9EC, 0x0262F97A, 0x9B6BA8C0, 0xEC6C9856, 1303 0x7CD385C7, 0x0BD4B551, 0x92DDE4EB, 0xE5DAD47D, 1304 0x7BBE41DE, 0x0CB97148, 0x95B020F2, 0xE2B71064, 1305 0x6FBF1D91, 0x18B82D07, 0x81B17CBD, 0xF6B64C2B, 1306 0x68D2D988, 0x1FD5E91E, 0x86DCB8A4, 0xF1DB8832, 1307 0x616495A3, 0x1663A535, 0x8F6AF48F, 0xF86DC419, 1308 0x660951BA, 0x110E612C, 0x88073096, 0xFF000000 1309 }; 1310