vpoio.c (67164) | vpoio.c (70608) |
---|---|
1/*- 2 * Copyright (c) 1998, 1999 Nicolas Souchu | 1/*- 2 * Copyright (c) 1998, 1999 Nicolas Souchu |
3 * Copyright (c) 2000 Alcove - Nicolas Souchu |
|
3 * All rights reserved. 4 * 5 * Redistribution 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, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright --- 7 unchanged lines hidden (view full) --- 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * | 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright --- 7 unchanged lines hidden (view full) --- 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 NEGLIGENCE 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 * |
26 * $FreeBSD: head/sys/dev/ppbus/vpoio.c 67164 2000-10-15 14:19:01Z phk $ | 27 * $FreeBSD: head/sys/dev/ppbus/vpoio.c 70608 2001-01-02 21:29:06Z nsouch $ |
27 * 28 */ 29 30#ifdef _KERNEL 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/module.h> 34#include <sys/bus.h> --- 324 unchanged lines hidden (view full) --- 359 device_t ppbus = device_get_parent(vpo->vpo_dev); 360 int error, ret; 361 362 /* allocate the bus, then apply microsequences */ 363 if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_DONTWAIT))) 364 return (error); 365 366 ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret); | 28 * 29 */ 30 31#ifdef _KERNEL 32#include <sys/param.h> 33#include <sys/systm.h> 34#include <sys/module.h> 35#include <sys/bus.h> --- 324 unchanged lines hidden (view full) --- 360 device_t ppbus = device_get_parent(vpo->vpo_dev); 361 int error, ret; 362 363 /* allocate the bus, then apply microsequences */ 364 if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_DONTWAIT))) 365 return (error); 366 367 ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret); |
368 /* Force disconnection */ |
|
367 | 369 |
368 if (PPB_IN_EPP_MODE(ppbus)) | 370 /* Try to enter EPP mode, then connect to the drive in EPP mode */ 371 if (ppb_set_mode(ppbus, PPB_EPP) != -1) { 372 /* call manually the microseq instead of using the appropriate function 373 * since we already requested the ppbus */ |
369 ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_epp_microseq, &ret); | 374 ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_epp_microseq, &ret); |
370 else 371 ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret); | 375 } |
372 | 376 |
373 ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret); 374 if (!ret) { | 377 /* If EPP mode switch failed or ZIP connection in EPP mode failed, 378 * try to connect in NIBBLE mode */ 379 if (!vpoio_in_disk_mode(vpo)) { |
375 | 380 |
376 /* try spp mode (maybe twice or because previous mode was PS2) 377 * NIBBLE mode will be restored on next transfers if detection 378 * succeed | 381 /* The interface must be at least PS/2 or NIBBLE capable. 382 * There is no way to know if the ZIP will work with 383 * PS/2 mode since PS/2 and SPP both use the same connect 384 * sequence. One must supress PS/2 with boot flags if 385 * PS/2 mode fails (see ppc(4)). |
379 */ | 386 */ |
380 ppb_set_mode(ppbus, PPB_NIBBLE); 381 ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret); | 387 if (ppb_set_mode(ppbus, PPB_PS2) != -1) { 388 vpo->vpo_mode_found = VP0_MODE_PS2; 389 } else { 390 if (ppb_set_mode(ppbus, PPB_NIBBLE) == -1) 391 goto error; |
382 | 392 |
383 ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret); 384 if (!ret) { | 393 vpo->vpo_mode_found = VP0_MODE_NIBBLE; 394 } 395 396 /* Can't know if the interface is capable of PS/2 yet */ 397 ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret); 398 if (!vpoio_in_disk_mode(vpo)) { 399 vpo->vpo_mode_found = VP0_MODE_UNDEFINED; |
385 if (bootverbose) 386 printf("vpo%d: can't connect to the drive\n", 387 vpo->vpo_unit); 388 389 /* disconnect and release the bus */ 390 ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, 391 &ret); 392 goto error; 393 } | 400 if (bootverbose) 401 printf("vpo%d: can't connect to the drive\n", 402 vpo->vpo_unit); 403 404 /* disconnect and release the bus */ 405 ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, 406 &ret); 407 goto error; 408 } |
409 } else { 410 vpo->vpo_mode_found = VP0_MODE_EPP; |
|
394 } 395 396 /* send SCSI reset signal */ 397 vpoio_reset(vpo); 398 399 ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret); 400 401 /* ensure we are disconnected or daisy chained peripheral 402 * may cause serious problem to the disk */ | 411 } 412 413 /* send SCSI reset signal */ 414 vpoio_reset(vpo); 415 416 ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret); 417 418 /* ensure we are disconnected or daisy chained peripheral 419 * may cause serious problem to the disk */ |
403 404 ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret); 405 if (ret) { | 420 if (vpoio_in_disk_mode(vpo)) { |
406 if (bootverbose) 407 printf("vpo%d: can't disconnect from the drive\n", 408 vpo->vpo_unit); 409 goto error; 410 } 411 412 ppb_release_bus(ppbus, vpo->vpo_dev); 413 return (0); --- 10 unchanged lines hidden (view full) --- 424vpoio_outstr(struct vpoio_data *vpo, char *buffer, int size) 425{ 426 device_t ppbus = device_get_parent(vpo->vpo_dev); 427 int error = 0; 428 429 ppb_MS_exec(ppbus, vpo->vpo_dev, MS_OP_PUT, (union ppb_insarg)buffer, 430 (union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error); 431 | 421 if (bootverbose) 422 printf("vpo%d: can't disconnect from the drive\n", 423 vpo->vpo_unit); 424 goto error; 425 } 426 427 ppb_release_bus(ppbus, vpo->vpo_dev); 428 return (0); --- 10 unchanged lines hidden (view full) --- 439vpoio_outstr(struct vpoio_data *vpo, char *buffer, int size) 440{ 441 device_t ppbus = device_get_parent(vpo->vpo_dev); 442 int error = 0; 443 444 ppb_MS_exec(ppbus, vpo->vpo_dev, MS_OP_PUT, (union ppb_insarg)buffer, 445 (union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error); 446 |
432#if 0 433 /* XXX EPP 1.9 not implemented with microsequences */ 434 else { 435 436 ppb_reset_epp_timeout(ppbus); 437 ppb_wctr(ppbus, H_AUTO | H_SELIN | H_INIT | H_STROBE); 438 439 if (((long) buffer | size) & 0x03) 440 ppb_outsb_epp(ppbus, 441 buffer, size); 442 else 443 ppb_outsl_epp(ppbus, 444 buffer, size/4); 445 446 if ((ppb_rstr(ppbus) & TIMEOUT)) { 447 error = VP0_EPPDATA_TIMEOUT; 448 goto error; 449 } 450 451 ppb_wctr(ppbus, H_AUTO | H_nSELIN | H_INIT | H_STROBE); 452 } 453#endif | |
454 ppb_ecp_sync(ppbus); 455 456 return (error); 457} 458 459/* 460 * vpoio_instr() 461 */ 462static int 463vpoio_instr(struct vpoio_data *vpo, char *buffer, int size) 464{ 465 device_t ppbus = device_get_parent(vpo->vpo_dev); 466 int error = 0; 467 468 ppb_MS_exec(ppbus, vpo->vpo_dev, MS_OP_GET, (union ppb_insarg)buffer, 469 (union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error); 470 | 447 ppb_ecp_sync(ppbus); 448 449 return (error); 450} 451 452/* 453 * vpoio_instr() 454 */ 455static int 456vpoio_instr(struct vpoio_data *vpo, char *buffer, int size) 457{ 458 device_t ppbus = device_get_parent(vpo->vpo_dev); 459 int error = 0; 460 461 ppb_MS_exec(ppbus, vpo->vpo_dev, MS_OP_GET, (union ppb_insarg)buffer, 462 (union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error); 463 |
471#if 0 472 /* XXX EPP 1.9 not implemented with microsequences */ 473 else { 474 475 ppb_reset_epp_timeout(ppbus); 476 ppb_wctr(ppbus, PCD | 477 H_AUTO | H_SELIN | H_INIT | H_STROBE); 478 479 if (((long) buffer | size) & 0x03) 480 ppb_insb_epp(ppbus, 481 buffer, size); 482 else 483 ppb_insl_epp(ppbus, 484 buffer, size/4); 485 486 if ((ppb_rstr(ppbus) & TIMEOUT)) { 487 error = VP0_EPPDATA_TIMEOUT; 488 goto error; 489 } 490 491 ppb_wctr(ppbus, PCD | 492 H_AUTO | H_nSELIN | H_INIT | H_STROBE); 493 } 494#endif | |
495 ppb_ecp_sync(ppbus); 496 497 return (error); 498} 499 500static char 501vpoio_select(struct vpoio_data *vpo, int initiator, int target) 502{ --- 106 unchanged lines hidden (view full) --- 609 * 610 * Low level attachment of vpo device 611 * 612 */ 613int 614vpoio_attach(struct vpoio_data *vpo) 615{ 616 device_t ppbus = device_get_parent(vpo->vpo_dev); | 464 ppb_ecp_sync(ppbus); 465 466 return (error); 467} 468 469static char 470vpoio_select(struct vpoio_data *vpo, int initiator, int target) 471{ --- 106 unchanged lines hidden (view full) --- 578 * 579 * Low level attachment of vpo device 580 * 581 */ 582int 583vpoio_attach(struct vpoio_data *vpo) 584{ 585 device_t ppbus = device_get_parent(vpo->vpo_dev); |
617 int epp; | 586 int error = 0; |
618 619 vpo->vpo_nibble_inbyte_msq = (struct ppb_microseq *)malloc( 620 sizeof(nibble_inbyte_submicroseq), M_DEVBUF, M_NOWAIT); 621 622 if (!vpo->vpo_nibble_inbyte_msq) 623 return (ENXIO); 624 625 bcopy((void *)nibble_inbyte_submicroseq, 626 (void *)vpo->vpo_nibble_inbyte_msq, 627 sizeof(nibble_inbyte_submicroseq)); 628 629 INIT_NIBBLE_INBYTE_SUBMICROSEQ(vpo); 630 631 /* 632 * Initialize mode dependent in/out microsequences 633 */ | 587 588 vpo->vpo_nibble_inbyte_msq = (struct ppb_microseq *)malloc( 589 sizeof(nibble_inbyte_submicroseq), M_DEVBUF, M_NOWAIT); 590 591 if (!vpo->vpo_nibble_inbyte_msq) 592 return (ENXIO); 593 594 bcopy((void *)nibble_inbyte_submicroseq, 595 (void *)vpo->vpo_nibble_inbyte_msq, 596 sizeof(nibble_inbyte_submicroseq)); 597 598 INIT_NIBBLE_INBYTE_SUBMICROSEQ(vpo); 599 600 /* 601 * Initialize mode dependent in/out microsequences 602 */ |
634 ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT); | 603 if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT))) 604 goto error; |
635 | 605 |
636 /* enter NIBBLE mode to configure submsq */ 637 if (ppb_set_mode(ppbus, PPB_NIBBLE) != -1) { 638 639 ppb_MS_GET_init(ppbus, vpo->vpo_dev, vpo->vpo_nibble_inbyte_msq); 640 641 ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq); 642 } 643 644 /* enter PS2 mode to configure submsq */ 645 if (ppb_set_mode(ppbus, PPB_PS2) != -1) { 646 | 606 /* ppbus sets automatically the last mode entered during detection */ 607 switch (vpo->vpo_mode_found) { 608 case VP0_MODE_EPP: 609 ppb_MS_GET_init(ppbus, vpo->vpo_dev, epp17_instr_body); 610 ppb_MS_PUT_init(ppbus, vpo->vpo_dev, epp17_outstr_body); 611 printf("vpo%d: EPP mode\n", vpo->vpo_unit); 612 break; 613 case VP0_MODE_PS2: |
647 ppb_MS_GET_init(ppbus, vpo->vpo_dev, ps2_inbyte_submicroseq); | 614 ppb_MS_GET_init(ppbus, vpo->vpo_dev, ps2_inbyte_submicroseq); |
648 | |
649 ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq); | 615 ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq); |
650 } 651 652 epp = ppb_get_epp_protocol(ppbus); 653 654 /* enter EPP mode to configure submsq */ 655 if (ppb_set_mode(ppbus, PPB_EPP) != -1) { 656 657 switch (epp) { 658 case EPP_1_9: 659 /* XXX EPP 1.9 support should be improved */ 660 case EPP_1_7: 661 ppb_MS_GET_init(ppbus, vpo->vpo_dev, epp17_instr_body); 662 663 ppb_MS_PUT_init(ppbus, vpo->vpo_dev, epp17_outstr_body); 664 break; 665 default: 666 panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__, 667 epp); 668 } 669 } 670 671 /* try to enter EPP or PS/2 mode, NIBBLE otherwise */ 672 if (ppb_set_mode(ppbus, PPB_EPP) != -1) { 673 switch (epp) { 674 case EPP_1_9: 675 printf("vpo%d: EPP 1.9 mode\n", vpo->vpo_unit); 676 break; 677 case EPP_1_7: 678 printf("vpo%d: EPP 1.7 mode\n", vpo->vpo_unit); 679 break; 680 default: 681 panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__, 682 epp); 683 } 684 } else if (ppb_set_mode(ppbus, PPB_PS2) != -1) | |
685 printf("vpo%d: PS2 mode\n", vpo->vpo_unit); | 616 printf("vpo%d: PS2 mode\n", vpo->vpo_unit); |
686 687 else if (ppb_set_mode(ppbus, PPB_NIBBLE) != -1) | 617 break; 618 case VP0_MODE_NIBBLE: 619 ppb_MS_GET_init(ppbus, vpo->vpo_dev, vpo->vpo_nibble_inbyte_msq); 620 ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq); |
688 printf("vpo%d: NIBBLE mode\n", vpo->vpo_unit); | 621 printf("vpo%d: NIBBLE mode\n", vpo->vpo_unit); |
689 690 else { 691 printf("vpo%d: can't enter NIBBLE, PS2 or EPP mode\n", 692 vpo->vpo_unit); 693 694 ppb_release_bus(ppbus, vpo->vpo_dev); 695 696 free(vpo->vpo_nibble_inbyte_msq, M_DEVBUF); 697 return (ENXIO); | 622 break; 623 default: 624 panic("vpo: unknown mode %d", vpo->vpo_mode_found); |
698 } 699 700 ppb_release_bus(ppbus, vpo->vpo_dev); 701 | 625 } 626 627 ppb_release_bus(ppbus, vpo->vpo_dev); 628 |
702 return (0); | 629error: 630 return (error); |
703} 704 705/* 706 * vpoio_reset_bus() 707 * 708 */ 709int 710vpoio_reset_bus(struct vpoio_data *vpo) --- 134 unchanged lines hidden --- | 631} 632 633/* 634 * vpoio_reset_bus() 635 * 636 */ 637int 638vpoio_reset_bus(struct vpoio_data *vpo) --- 134 unchanged lines hidden --- |