immio.c (184130) | immio.c (185003) |
---|---|
1/*- 2 * Copyright (c) 1998, 1999 Nicolas Souchu 3 * Copyright (c) 2001 Alcove - Nicolas Souchu 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: --- 14 unchanged lines hidden (view full) --- 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 * 27 * 28 */ 29 30#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1998, 1999 Nicolas Souchu 3 * Copyright (c) 2001 Alcove - Nicolas Souchu 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: --- 14 unchanged lines hidden (view full) --- 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 * 27 * 28 */ 29 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: head/sys/dev/ppbus/immio.c 184130 2008-10-21 18:30:10Z jhb $"); | 31__FBSDID("$FreeBSD: head/sys/dev/ppbus/immio.c 185003 2008-11-16 17:42:02Z jhb $"); |
32 33/* 34 * Iomega ZIP+ Matchmaker Parallel Port Interface driver 35 * 36 * Thanks to David Campbell work on the Linux driver and the Iomega specs 37 * Thanks to Thiebault Moeglin for the drive 38 */ 39#ifdef _KERNEL --- 205 unchanged lines hidden (view full) --- 245 246/* 247 * This is the sub-microsequence for MS_PUT in both NIBBLE and PS2 modes 248 */ 249static struct ppb_microseq spp_outbyte_submicroseq[] = { 250 MS_CASS(0x4), 251 252/* loop: */ | 32 33/* 34 * Iomega ZIP+ Matchmaker Parallel Port Interface driver 35 * 36 * Thanks to David Campbell work on the Linux driver and the Iomega specs 37 * Thanks to Thiebault Moeglin for the drive 38 */ 39#ifdef _KERNEL --- 205 unchanged lines hidden (view full) --- 245 246/* 247 * This is the sub-microsequence for MS_PUT in both NIBBLE and PS2 modes 248 */ 249static struct ppb_microseq spp_outbyte_submicroseq[] = { 250 MS_CASS(0x4), 251 252/* loop: */ |
253 MS_RASSERT_P(1, MS_REG_DTR), | 253 MS_RASSERT_P(1, MS_REG_DTR), |
254 MS_CASS(0x5), 255 MS_DBRA(0), /* decrement counter */ | 254 MS_CASS(0x5), 255 MS_DBRA(0), /* decrement counter */ |
256 MS_RASSERT_P(1, MS_REG_DTR), | 256 MS_RASSERT_P(1, MS_REG_DTR), |
257 MS_CASS(0x0), 258 MS_DBRA(-6 /* loop */), 259 260 /* return from the put call */ 261 MS_CASS(0x4), 262 MS_RET(0) 263}; 264 265/* EPP 1.7 microsequences, ptr and len set at runtime */ 266static struct ppb_microseq epp17_outstr[] = { 267 MS_CASS(0x4), | 257 MS_CASS(0x0), 258 MS_DBRA(-6 /* loop */), 259 260 /* return from the put call */ 261 MS_CASS(0x4), 262 MS_RET(0) 263}; 264 265/* EPP 1.7 microsequences, ptr and len set at runtime */ 266static struct ppb_microseq epp17_outstr[] = { 267 MS_CASS(0x4), |
268 MS_RASSERT_P(MS_ACCUM, MS_REG_EPP_D), | 268 MS_RASSERT_P(MS_ACCUM, MS_REG_EPP_D), |
269 MS_CASS(0xc), 270 MS_RET(0), 271}; 272 273static struct ppb_microseq epp17_instr[] = { 274 MS_CASS(PCD | 0x4), | 269 MS_CASS(0xc), 270 MS_RET(0), 271}; 272 273static struct ppb_microseq epp17_instr[] = { 274 MS_CASS(PCD | 0x4), |
275 MS_RFETCH_P(MS_ACCUM, MS_REG_EPP_D, MS_FETCH_ALL), | 275 MS_RFETCH_P(MS_ACCUM, MS_REG_EPP_D, MS_FETCH_ALL), |
276 MS_CASS(PCD | 0xc), 277 MS_RET(0), 278}; 279 280static int 281imm_disconnect(struct vpoio_data *vpo, int *connected, int release_bus) 282{ 283 DECLARE_CPP_MICROSEQ; --- 127 unchanged lines hidden (view full) --- 411 } 412 413 /* send SCSI reset signal */ 414 ppb_MS_microseq(ppbus, vpo->vpo_dev, reset_microseq, NULL); 415 416 /* release the bus now */ 417 imm_disconnect(vpo, &error, 1); 418 | 276 MS_CASS(PCD | 0xc), 277 MS_RET(0), 278}; 279 280static int 281imm_disconnect(struct vpoio_data *vpo, int *connected, int release_bus) 282{ 283 DECLARE_CPP_MICROSEQ; --- 127 unchanged lines hidden (view full) --- 411 } 412 413 /* send SCSI reset signal */ 414 ppb_MS_microseq(ppbus, vpo->vpo_dev, reset_microseq, NULL); 415 416 /* release the bus now */ 417 imm_disconnect(vpo, &error, 1); 418 |
419 /* ensure we are disconnected or daisy chained peripheral | 419 /* ensure we are disconnected or daisy chained peripheral |
420 * may cause serious problem to the disk */ 421 422 if (error) { 423 if (bootverbose) 424 device_printf(vpo->vpo_dev, 425 "can't disconnect from the drive\n"); 426 goto error; 427 } --- 46 unchanged lines hidden (view full) --- 474{ 475 DECLARE_SELECT_MICROSEQUENCE; 476 device_t ppbus = device_get_parent(vpo->vpo_dev); 477 int ret; 478 479 /* initialize the select microsequence */ 480 ppb_MS_init_msq(select_microseq, 1, 481 SELECT_TARGET, 1 << initiator | 1 << target); | 420 * may cause serious problem to the disk */ 421 422 if (error) { 423 if (bootverbose) 424 device_printf(vpo->vpo_dev, 425 "can't disconnect from the drive\n"); 426 goto error; 427 } --- 46 unchanged lines hidden (view full) --- 474{ 475 DECLARE_SELECT_MICROSEQUENCE; 476 device_t ppbus = device_get_parent(vpo->vpo_dev); 477 int ret; 478 479 /* initialize the select microsequence */ 480 ppb_MS_init_msq(select_microseq, 1, 481 SELECT_TARGET, 1 << initiator | 1 << target); |
482 | 482 |
483 ppb_MS_microseq(ppbus, vpo->vpo_dev, select_microseq, &ret); 484 485 return (ret); 486} 487 488/* 489 * imm_wait() 490 * --- 18 unchanged lines hidden (view full) --- 509 510 ppb_MS_init_msq(wait_microseq, 2, 511 WAIT_RET, (void *)&ret, 512 WAIT_TMO, tmo); 513 514 ppb_MS_microseq(ppbus, vpo->vpo_dev, wait_microseq, &err); 515 516 if (err) | 483 ppb_MS_microseq(ppbus, vpo->vpo_dev, select_microseq, &ret); 484 485 return (ret); 486} 487 488/* 489 * imm_wait() 490 * --- 18 unchanged lines hidden (view full) --- 509 510 ppb_MS_init_msq(wait_microseq, 2, 511 WAIT_RET, (void *)&ret, 512 WAIT_TMO, tmo); 513 514 ppb_MS_microseq(ppbus, vpo->vpo_dev, wait_microseq, &err); 515 516 if (err) |
517 return (0); /* command timed out */ | 517 return (0); /* command timed out */ |
518 519 return(ret); 520} 521 522static int 523imm_negociate(struct vpoio_data *vpo) 524{ 525 DECLARE_NEGOCIATE_MICROSEQ; --- 9 unchanged lines hidden (view full) --- 535 return (0); 536 537#if 0 /* XXX use standalone code not to depend on ppb_1284 code yet */ 538 ret = ppb_1284_negociate(ppbus, negociate_mode); 539 540 if (ret) 541 return (VP0_ENEGOCIATE); 542#endif | 518 519 return(ret); 520} 521 522static int 523imm_negociate(struct vpoio_data *vpo) 524{ 525 DECLARE_NEGOCIATE_MICROSEQ; --- 9 unchanged lines hidden (view full) --- 535 return (0); 536 537#if 0 /* XXX use standalone code not to depend on ppb_1284 code yet */ 538 ret = ppb_1284_negociate(ppbus, negociate_mode); 539 540 if (ret) 541 return (VP0_ENEGOCIATE); 542#endif |
543 | 543 |
544 ppb_MS_init_msq(negociate_microseq, 1, 545 NEGOCIATED_MODE, negociate_mode); 546 547 ppb_MS_microseq(ppbus, vpo->vpo_dev, negociate_microseq, &ret); 548 549 return (ret); 550} 551 --- 23 unchanged lines hidden (view full) --- 575 * imm_attach() 576 * 577 * Low level attachment of vpo device 578 * 579 */ 580int 581imm_attach(struct vpoio_data *vpo) 582{ | 544 ppb_MS_init_msq(negociate_microseq, 1, 545 NEGOCIATED_MODE, negociate_mode); 546 547 ppb_MS_microseq(ppbus, vpo->vpo_dev, negociate_microseq, &ret); 548 549 return (ret); 550} 551 --- 23 unchanged lines hidden (view full) --- 575 * imm_attach() 576 * 577 * Low level attachment of vpo device 578 * 579 */ 580int 581imm_attach(struct vpoio_data *vpo) 582{ |
583 DECLARE_NIBBLE_INBYTE_SUBMICROSEQ; | 583 DECLARE_NIBBLE_INBYTE_SUBMICROSEQ; |
584 device_t ppbus = device_get_parent(vpo->vpo_dev); 585 int error = 0; 586 587 /* 588 * Initialize microsequence code 589 */ 590 vpo->vpo_nibble_inbyte_msq = (struct ppb_microseq *)malloc( 591 sizeof(nibble_inbyte_submicroseq), M_DEVBUF, M_NOWAIT); --- 4 unchanged lines hidden (view full) --- 596 bcopy((void *)nibble_inbyte_submicroseq, 597 (void *)vpo->vpo_nibble_inbyte_msq, 598 sizeof(nibble_inbyte_submicroseq)); 599 600 ppb_MS_init_msq(vpo->vpo_nibble_inbyte_msq, 4, 601 INB_NIBBLE_H, (void *)&(vpo)->vpo_nibble.h, 602 INB_NIBBLE_L, (void *)&(vpo)->vpo_nibble.l, 603 INB_NIBBLE_F, nibble_inbyte_hook, | 584 device_t ppbus = device_get_parent(vpo->vpo_dev); 585 int error = 0; 586 587 /* 588 * Initialize microsequence code 589 */ 590 vpo->vpo_nibble_inbyte_msq = (struct ppb_microseq *)malloc( 591 sizeof(nibble_inbyte_submicroseq), M_DEVBUF, M_NOWAIT); --- 4 unchanged lines hidden (view full) --- 596 bcopy((void *)nibble_inbyte_submicroseq, 597 (void *)vpo->vpo_nibble_inbyte_msq, 598 sizeof(nibble_inbyte_submicroseq)); 599 600 ppb_MS_init_msq(vpo->vpo_nibble_inbyte_msq, 4, 601 INB_NIBBLE_H, (void *)&(vpo)->vpo_nibble.h, 602 INB_NIBBLE_L, (void *)&(vpo)->vpo_nibble.l, 603 INB_NIBBLE_F, nibble_inbyte_hook, |
604 INB_NIBBLE_P, (void *)&(vpo)->vpo_nibble); | 604 INB_NIBBLE_P, (void *)&(vpo)->vpo_nibble); |
605 606 /* 607 * Initialize mode dependent in/out microsequences 608 */ 609 if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT))) 610 goto error; 611 612 /* ppbus automatically restore the last mode entered during detection */ --- 48 unchanged lines hidden (view full) --- 661} 662 663/* 664 * imm_do_scsi() 665 * 666 * Send an SCSI command 667 * 668 */ | 605 606 /* 607 * Initialize mode dependent in/out microsequences 608 */ 609 if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT))) 610 goto error; 611 612 /* ppbus automatically restore the last mode entered during detection */ --- 48 unchanged lines hidden (view full) --- 661} 662 663/* 664 * imm_do_scsi() 665 * 666 * Send an SCSI command 667 * 668 */ |
669int | 669int |
670imm_do_scsi(struct vpoio_data *vpo, int host, int target, char *command, 671 int clen, char *buffer, int blen, int *result, int *count, 672 int *ret) 673{ 674 device_t ppbus = device_get_parent(vpo->vpo_dev); 675 register char r; 676 char l, h = 0; 677 int len, error = 0, not_connected = 0; --- 7 unchanged lines hidden (view full) --- 685 * Should we allow this call to be interruptible? 686 * The only way to report the interruption is to return 687 * EIO to upper SCSI code :^( 688 */ 689 if ((error = imm_connect(vpo, PPB_WAIT|PPB_INTR, ¬_connected, 1))) 690 return (error); 691 692 if (not_connected) { | 670imm_do_scsi(struct vpoio_data *vpo, int host, int target, char *command, 671 int clen, char *buffer, int blen, int *result, int *count, 672 int *ret) 673{ 674 device_t ppbus = device_get_parent(vpo->vpo_dev); 675 register char r; 676 char l, h = 0; 677 int len, error = 0, not_connected = 0; --- 7 unchanged lines hidden (view full) --- 685 * Should we allow this call to be interruptible? 686 * The only way to report the interruption is to return 687 * EIO to upper SCSI code :^( 688 */ 689 if ((error = imm_connect(vpo, PPB_WAIT|PPB_INTR, ¬_connected, 1))) 690 return (error); 691 692 if (not_connected) { |
693 *ret = VP0_ECONNECT; goto error; | 693 *ret = VP0_ECONNECT; 694 goto error; |
694 } 695 696 /* 697 * Select the drive ... 698 */ 699 if ((*ret = imm_select(vpo,host,target))) 700 goto error; 701 --- 7 unchanged lines hidden (view full) --- 709 } 710 if (imm_outstr(vpo, &command[k], 2)) { 711 *ret = VP0_EPPDATA_TIMEOUT; 712 goto error; 713 } 714 } 715 716 if (!(r = imm_wait(vpo, VP0_LOW_SPINTMO))) { | 695 } 696 697 /* 698 * Select the drive ... 699 */ 700 if ((*ret = imm_select(vpo,host,target))) 701 goto error; 702 --- 7 unchanged lines hidden (view full) --- 710 } 711 if (imm_outstr(vpo, &command[k], 2)) { 712 *ret = VP0_EPPDATA_TIMEOUT; 713 goto error; 714 } 715 } 716 717 if (!(r = imm_wait(vpo, VP0_LOW_SPINTMO))) { |
717 *ret = VP0_ESTATUS_TIMEOUT; goto error; | 718 *ret = VP0_ESTATUS_TIMEOUT; 719 goto error; |
718 } 719 720 if ((r & 0x30) == 0x10) { 721 if (imm_negociate(vpo)) { 722 *ret = VP0_ENEGOCIATE; 723 goto error; 724 } else 725 negociated = 1; 726 } 727 | 720 } 721 722 if ((r & 0x30) == 0x10) { 723 if (imm_negociate(vpo)) { 724 *ret = VP0_ENEGOCIATE; 725 goto error; 726 } else 727 negociated = 1; 728 } 729 |
728 /* 729 * Complete transfer ... | 730 /* 731 * Complete transfer ... |
730 */ 731 *count = 0; 732 for (;;) { 733 734 if (!(r = imm_wait(vpo, VP0_LOW_SPINTMO))) { | 732 */ 733 *count = 0; 734 for (;;) { 735 736 if (!(r = imm_wait(vpo, VP0_LOW_SPINTMO))) { |
735 *ret = VP0_ESTATUS_TIMEOUT; goto error; | 737 *ret = VP0_ESTATUS_TIMEOUT; 738 goto error; |
736 } 737 738 /* stop when the ZIP+ wants to send status */ 739 if (r == (char)0xb8) 740 break; 741 742 if (*count >= blen) { 743 *ret = VP0_EDATA_OVERFLOW; --- 33 unchanged lines hidden (view full) --- 777 */ 778 if (imm_negociate(vpo)) { 779 *ret = VP0_ENEGOCIATE; 780 goto error; 781 } else 782 negociated = 1; 783 784 if (imm_instr(vpo, &l, 1)) { | 739 } 740 741 /* stop when the ZIP+ wants to send status */ 742 if (r == (char)0xb8) 743 break; 744 745 if (*count >= blen) { 746 *ret = VP0_EDATA_OVERFLOW; --- 33 unchanged lines hidden (view full) --- 780 */ 781 if (imm_negociate(vpo)) { 782 *ret = VP0_ENEGOCIATE; 783 goto error; 784 } else 785 negociated = 1; 786 787 if (imm_instr(vpo, &l, 1)) { |
785 *ret = VP0_EOTHER; goto error; | 788 *ret = VP0_EOTHER; 789 goto error; |
786 } 787 788 /* check if the ZIP+ wants to send more status */ 789 if (imm_wait(vpo, VP0_FAST_SPINTMO) == (char)0xb8) 790 if (imm_instr(vpo, &h, 1)) { | 790 } 791 792 /* check if the ZIP+ wants to send more status */ 793 if (imm_wait(vpo, VP0_FAST_SPINTMO) == (char)0xb8) 794 if (imm_instr(vpo, &h, 1)) { |
791 *ret = VP0_EOTHER+2; goto error; | 795 *ret = VP0_EOTHER + 2; 796 goto error; |
792 } 793 794 /* Experience showed that we should discard this */ 795 if (h == (char) -1) 796 h = 0; 797 798 *result = ((int) h << 8) | ((int) l & 0xff); 799 800error: 801 if ((PPB_IN_NIBBLE_MODE(ppbus) || 802 PPB_IN_PS2_MODE(ppbus)) && negociated) 803 ppb_MS_microseq(ppbus, vpo->vpo_dev, transfer_epilog, NULL); 804 805 /* return to printer state, release the ppbus */ 806 imm_disconnect(vpo, NULL, 1); 807 808 return (0); 809} | 797 } 798 799 /* Experience showed that we should discard this */ 800 if (h == (char) -1) 801 h = 0; 802 803 *result = ((int) h << 8) | ((int) l & 0xff); 804 805error: 806 if ((PPB_IN_NIBBLE_MODE(ppbus) || 807 PPB_IN_PS2_MODE(ppbus)) && negociated) 808 ppb_MS_microseq(ppbus, vpo->vpo_dev, transfer_epilog, NULL); 809 810 /* return to printer state, release the ppbus */ 811 imm_disconnect(vpo, NULL, 1); 812 813 return (0); 814} |