Deleted Added
full compact
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 ---