amr.c (58496) | amr.c (58883) |
---|---|
1/*- 2 * Copyright (c) 1999 Michael Smith 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 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 * | 1/*- 2 * Copyright (c) 1999 Michael Smith 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 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 * |
26 * $FreeBSD: head/sys/dev/amr/amr.c 58496 2000-03-23 18:33:19Z msmith $ | 26 * $FreeBSD: head/sys/dev/amr/amr.c 58883 2000-04-01 00:35:15Z msmith $ |
27 */ 28 29/* 30 * Driver for the AMI MegaRaid family of controllers 31 */ 32 33#include <sys/param.h> 34#include <sys/systm.h> --- 68 unchanged lines hidden (view full) --- 103/* 104 * Command buffer allocation. 105 */ 106static struct amr_command *amr_alloccmd(struct amr_softc *sc); 107static void amr_releasecmd(struct amr_command *ac); 108static void amr_freecmd(struct amr_command *ac); 109 110/* | 27 */ 28 29/* 30 * Driver for the AMI MegaRaid family of controllers 31 */ 32 33#include <sys/param.h> 34#include <sys/systm.h> --- 68 unchanged lines hidden (view full) --- 103/* 104 * Command buffer allocation. 105 */ 106static struct amr_command *amr_alloccmd(struct amr_softc *sc); 107static void amr_releasecmd(struct amr_command *ac); 108static void amr_freecmd(struct amr_command *ac); 109 110/* |
111 * Status monitoring 112 */ 113static void amr_periodic(void *data); 114 115/* |
|
111 * Interface-specific shims 112 */ 113static void amr_quartz_submit_command(struct amr_softc *sc); 114static int amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave); 115static void amr_quartz_attach_mailbox(struct amr_softc *sc); 116 117static void amr_std_submit_command(struct amr_softc *sc); 118static int amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave); --- 18 unchanged lines hidden (view full) --- 137void 138amr_free(struct amr_softc *sc) 139{ 140 struct amr_command *ac; 141 u_int8_t *p; 142 143 debug("called"); 144 | 116 * Interface-specific shims 117 */ 118static void amr_quartz_submit_command(struct amr_softc *sc); 119static int amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave); 120static void amr_quartz_attach_mailbox(struct amr_softc *sc); 121 122static void amr_std_submit_command(struct amr_softc *sc); 123static int amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave); --- 18 unchanged lines hidden (view full) --- 142void 143amr_free(struct amr_softc *sc) 144{ 145 struct amr_command *ac; 146 u_int8_t *p; 147 148 debug("called"); 149 |
150 /* cancel status timeout */ 151 untimeout(amr_periodic, sc, sc->amr_timeout); |
|
145 146 /* throw away any command buffers */ 147 while ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL) { 148 TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link); 149 amr_freecmd(ac); 150 } 151 152 /* destroy data-transfer DMA tag */ --- 247 unchanged lines hidden (view full) --- 400 return(ENXIO); 401 402 /* 403 * Rebuild the scatter/gather buffers now we know how many we need. 404 */ 405 if (amr_sglist_map(sc)) 406 return(ENXIO); 407 | 152 153 /* throw away any command buffers */ 154 while ((ac = TAILQ_FIRST(&sc->amr_freecmds)) != NULL) { 155 TAILQ_REMOVE(&sc->amr_freecmds, ac, ac_link); 156 amr_freecmd(ac); 157 } 158 159 /* destroy data-transfer DMA tag */ --- 247 unchanged lines hidden (view full) --- 407 return(ENXIO); 408 409 /* 410 * Rebuild the scatter/gather buffers now we know how many we need. 411 */ 412 if (amr_sglist_map(sc)) 413 return(ENXIO); 414 |
415 /* 416 * Start the timeout routine. 417 */ 418 sc->amr_timeout = timeout(amr_periodic, sc, hz); 419 |
|
408 return(0); 409} 410 411/******************************************************************************** 412 * Locate disk resources and attach children to them. 413 */ 414void 415amr_startup(struct amr_softc *sc) --- 115 unchanged lines hidden (view full) --- 531 /* delete all our child devices */ 532 for (i = 0; i < AMR_MAXLD; i++) { 533 if (sc->amr_drive[i].al_disk != 0) { 534 if ((error = device_delete_child(sc->amr_dev, sc->amr_drive[i].al_disk)) != 0) 535 goto out; 536 sc->amr_drive[i].al_disk = 0; 537 } 538 } | 420 return(0); 421} 422 423/******************************************************************************** 424 * Locate disk resources and attach children to them. 425 */ 426void 427amr_startup(struct amr_softc *sc) --- 115 unchanged lines hidden (view full) --- 543 /* delete all our child devices */ 544 for (i = 0; i < AMR_MAXLD; i++) { 545 if (sc->amr_drive[i].al_disk != 0) { 546 if ((error = device_delete_child(sc->amr_dev, sc->amr_drive[i].al_disk)) != 0) 547 goto out; 548 sc->amr_drive[i].al_disk = 0; 549 } 550 } |
539 bus_generic_detach(sc->amr_dev); | |
540 541 out: 542 splx(s); 543 return(error); 544} 545 546/******************************************************************************** 547 * Bring the controller to a quiescent state, ready for system suspend. --- 32 unchanged lines hidden (view full) --- 580/******************************************************************************* 581 * Take an interrupt, or be poked by other code to look for interrupt-worthy 582 * status. 583 */ 584void 585amr_intr(void *arg) 586{ 587 struct amr_softc *sc = (struct amr_softc *)arg; | 551 552 out: 553 splx(s); 554 return(error); 555} 556 557/******************************************************************************** 558 * Bring the controller to a quiescent state, ready for system suspend. --- 32 unchanged lines hidden (view full) --- 591/******************************************************************************* 592 * Take an interrupt, or be poked by other code to look for interrupt-worthy 593 * status. 594 */ 595void 596amr_intr(void *arg) 597{ 598 struct amr_softc *sc = (struct amr_softc *)arg; |
588 int worked; | |
589 | 599 |
590 debug("called on %p", sc); | 600 debug("called"); |
591 | 601 |
592 /* spin collecting finished commands, process them if we find anything */ 593 worked = 0; 594 while (amr_done(sc)) 595 worked = 1; 596 if (worked) 597 amr_complete(sc); | 602 /* collect finished commands, queue anything waiting */ 603 amr_done(sc); |
598}; 599 600/******************************************************************************* 601 * Receive a buf structure from a child device and queue it on a particular 602 * disk resource, then poke the disk resource to start as much work as it can. 603 */ 604int 605amr_submit_buf(struct amr_softc *sc, struct buf *bp) --- 56 unchanged lines hidden (view full) --- 662amr_submit_ioctl(struct amr_softc *sc, struct amr_logdrive *drive, u_long cmd, 663 caddr_t addr, int32_t flag, struct proc *p) 664{ 665 return(ENOTTY); 666} 667 668/******************************************************************************** 669 ******************************************************************************** | 604}; 605 606/******************************************************************************* 607 * Receive a buf structure from a child device and queue it on a particular 608 * disk resource, then poke the disk resource to start as much work as it can. 609 */ 610int 611amr_submit_buf(struct amr_softc *sc, struct buf *bp) --- 56 unchanged lines hidden (view full) --- 668amr_submit_ioctl(struct amr_softc *sc, struct amr_logdrive *drive, u_long cmd, 669 caddr_t addr, int32_t flag, struct proc *p) 670{ 671 return(ENOTTY); 672} 673 674/******************************************************************************** 675 ******************************************************************************** |
676 Status Monitoring 677 ******************************************************************************** 678 ********************************************************************************/ 679 680/******************************************************************************** 681 * Perform a periodic check of the controller status 682 */ 683static void 684amr_periodic(void *data) 685{ 686 struct amr_softc *sc = (struct amr_softc *)data; 687 int s, i; 688 689 debug("called"); 690 691 692 /* 693 * Check for commands that are massively late. This will need to be 694 * revisited if/when we deal with eg. device format commands. 695 * The 30 second value is entirely arbitrary. 696 */ 697 s = splbio(); 698 if (sc->amr_busycmdcount > 0) { 699 for (i = 0; i < AMR_MAXCMD; i++) { 700 /* 701 * If the command has been busy for more than 30 seconds, declare it 702 * wedged and retire it with an error. 703 */ 704 if ((sc->amr_busycmd[i] != NULL) && 705 (sc->amr_busycmd[i]->ac_status == AMR_STATUS_BUSY) && 706 ((sc->amr_busycmd[i]->ac_stamp + 30) < time_second)) { 707 device_printf(sc->amr_dev, "command %d wedged after 30 seconds\n", i); 708 sc->amr_busycmd[i]->ac_status = AMR_STATUS_WEDGED; 709 amr_completeio(sc->amr_busycmd[i]); 710 } 711 } 712 } 713 splx(s); 714 715 /* reschedule */ 716 sc->amr_timeout = timeout(amr_periodic, sc, hz); 717} 718 719 720/******************************************************************************** 721 ******************************************************************************** |
|
670 Command Wrappers 671 ******************************************************************************** 672 ********************************************************************************/ 673 674/******************************************************************************** 675 * Interrogate the controller for the operational parameters we require. 676 */ 677static int --- 15 unchanged lines hidden (view full) --- 693 } 694 /* first-time enquiry? */ 695 if (sc->amr_maxdrives == 0) { 696 device_printf(sc->amr_dev, "firmware %.4s bios %.4s %dMB memory\n", 697 ae->ae_adapter.aa_firmware, ae->ae_adapter.aa_bios, 698 ae->ae_adapter.aa_memorysize); 699 } 700 sc->amr_maxdrives = 8; | 722 Command Wrappers 723 ******************************************************************************** 724 ********************************************************************************/ 725 726/******************************************************************************** 727 * Interrogate the controller for the operational parameters we require. 728 */ 729static int --- 15 unchanged lines hidden (view full) --- 745 } 746 /* first-time enquiry? */ 747 if (sc->amr_maxdrives == 0) { 748 device_printf(sc->amr_dev, "firmware %.4s bios %.4s %dMB memory\n", 749 ae->ae_adapter.aa_firmware, ae->ae_adapter.aa_bios, 750 ae->ae_adapter.aa_memorysize); 751 } 752 sc->amr_maxdrives = 8; |
701 sc->amr_maxio = ae->ae_adapter.aa_maxio; | 753 754 /* 755 * Cap the maximum number of outstanding I/Os. AMI's Linux driver doesn't trust 756 * the controller's reported value, and lockups have been seen when we do. 757 */ 758 sc->amr_maxio = imin(ae->ae_adapter.aa_maxio, AMR_LIMITCMD); 759 |
702 for (i = 0; i < ae->ae_ldrv.al_numdrives; i++) { 703 sc->amr_drive[i].al_size = ae->ae_ldrv.al_size[i]; 704 sc->amr_drive[i].al_state = ae->ae_ldrv.al_state[i]; 705 sc->amr_drive[i].al_properties = ae->ae_ldrv.al_properties[i]; 706 debug(" drive %d: %d state %x properties %x\n", i, sc->amr_drive[i].al_size, 707 sc->amr_drive[i].al_state, sc->amr_drive[i].al_properties); 708 } 709 for (; i < AMR_MAXLD; i++) 710 sc->amr_drive[i].al_size = 0xffffffff; 711 free(ae, M_DEVBUF); 712 } else { | 760 for (i = 0; i < ae->ae_ldrv.al_numdrives; i++) { 761 sc->amr_drive[i].al_size = ae->ae_ldrv.al_size[i]; 762 sc->amr_drive[i].al_state = ae->ae_ldrv.al_state[i]; 763 sc->amr_drive[i].al_properties = ae->ae_ldrv.al_properties[i]; 764 debug(" drive %d: %d state %x properties %x\n", i, sc->amr_drive[i].al_size, 765 sc->amr_drive[i].al_state, sc->amr_drive[i].al_properties); 766 } 767 for (; i < AMR_MAXLD; i++) 768 sc->amr_drive[i].al_size = 0xffffffff; 769 free(ae, M_DEVBUF); 770 } else { |
771 /* 772 * The "40LD" (40 logical drive support) firmware is mentioned in the Linux 773 * driver, but no adapters from AMI appear to support it. 774 */ |
|
713 free(buf, M_DEVBUF); 714 sc->amr_maxdrives = 40; 715 716 /* get static product info */ 717 if ((buf = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODINFO, 0)) == NULL) { 718 device_printf(sc->amr_dev, "controller supports 40ld but CONFIG_PRODINFO failed\n"); 719 return(1); 720 } --- 38 unchanged lines hidden (view full) --- 759 760 /* build the command proper */ 761 mbox = (u_int8_t *)&ac->ac_mailbox; /* XXX want a real structure for this? */ 762 mbox[0] = cmd; 763 mbox[2] = cmdsub; 764 mbox[3] = cmdqual; 765 ac->ac_mailbox.mb_physaddr = ac->ac_dataphys; 766 | 775 free(buf, M_DEVBUF); 776 sc->amr_maxdrives = 40; 777 778 /* get static product info */ 779 if ((buf = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODINFO, 0)) == NULL) { 780 device_printf(sc->amr_dev, "controller supports 40ld but CONFIG_PRODINFO failed\n"); 781 return(1); 782 } --- 38 unchanged lines hidden (view full) --- 821 822 /* build the command proper */ 823 mbox = (u_int8_t *)&ac->ac_mailbox; /* XXX want a real structure for this? */ 824 mbox[0] = cmd; 825 mbox[2] = cmdsub; 826 mbox[3] = cmdqual; 827 ac->ac_mailbox.mb_physaddr = ac->ac_dataphys; 828 |
767 /* run the command in polled/wait mode as suits the current mode */ 768 if ((sc->amr_state & AMR_STATE_INTEN) ? amr_wait_command(ac) : amr_poll_command(ac)) | 829 /* can't assume that interrupts are going to work here, so play it safe */ 830 if (amr_poll_command(ac)) |
769 goto out; 770 error = ac->ac_status; 771 772 out: 773 if (ac != NULL) 774 amr_releasecmd(ac); 775 if ((error != 0) && (result != NULL)) { 776 free(result, M_DEVBUF); --- 18 unchanged lines hidden (view full) --- 795 /* get a command slot */ 796 ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT; 797 if (amr_getslot(ac)) 798 goto out; 799 800 /* build the command proper */ 801 ac->ac_mailbox.mb_command = AMR_CMD_FLUSH; 802 | 831 goto out; 832 error = ac->ac_status; 833 834 out: 835 if (ac != NULL) 836 amr_releasecmd(ac); 837 if ((error != 0) && (result != NULL)) { 838 free(result, M_DEVBUF); --- 18 unchanged lines hidden (view full) --- 857 /* get a command slot */ 858 ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT; 859 if (amr_getslot(ac)) 860 goto out; 861 862 /* build the command proper */ 863 ac->ac_mailbox.mb_command = AMR_CMD_FLUSH; 864 |
803 /* run the command in polled/wait mode as suits the current mode */ 804 if ((sc->amr_state & AMR_STATE_INTEN) ? amr_wait_command(ac) : amr_poll_command(ac)) | 865 /* we have to poll, as the system may be going down or otherwise damaged */ 866 if (amr_poll_command(ac)) |
805 goto out; 806 error = ac->ac_status; 807 808 out: 809 if (ac != NULL) 810 amr_releasecmd(ac); 811 return(error); 812} --- 10 unchanged lines hidden (view full) --- 823 struct amr_command *ac; 824 struct amrd_softc *amrd; 825 struct buf *bp; 826 int blkcount; 827 int driveno; 828 int cmd; 829 int s; 830 | 867 goto out; 868 error = ac->ac_status; 869 870 out: 871 if (ac != NULL) 872 amr_releasecmd(ac); 873 return(error); 874} --- 10 unchanged lines hidden (view full) --- 885 struct amr_command *ac; 886 struct amrd_softc *amrd; 887 struct buf *bp; 888 int blkcount; 889 int driveno; 890 int cmd; 891 int s; 892 |
893 /* avoid reentrancy */ 894 if (amr_lock_tas(sc, AMR_LOCK_STARTING)) 895 return; 896 |
|
831 /* spin until something prevents us from doing any work */ 832 s = splbio(); 833 for (;;) { 834 835 /* see if there's work to be done */ 836 if ((bp = bufq_first(&sc->amr_bufq)) == NULL) 837 break; 838 /* get a command */ --- 21 unchanged lines hidden (view full) --- 860 ac->ac_flags |= AMR_CMD_DATAOUT; 861 cmd = AMR_CMD_LWRITE; 862 } 863 864 /* map the command so the controller can work with it */ 865 amr_mapcmd(ac); 866 867 /* build a suitable I/O command (assumes 512-byte rounded transfers) */ | 897 /* spin until something prevents us from doing any work */ 898 s = splbio(); 899 for (;;) { 900 901 /* see if there's work to be done */ 902 if ((bp = bufq_first(&sc->amr_bufq)) == NULL) 903 break; 904 /* get a command */ --- 21 unchanged lines hidden (view full) --- 926 ac->ac_flags |= AMR_CMD_DATAOUT; 927 cmd = AMR_CMD_LWRITE; 928 } 929 930 /* map the command so the controller can work with it */ 931 amr_mapcmd(ac); 932 933 /* build a suitable I/O command (assumes 512-byte rounded transfers) */ |
868 amrd = (struct amrd_softc *)bp->b_driver1; 869 driveno = amrd->amrd_drive - &sc->amr_drive[0]; 870 blkcount = bp->b_bcount / AMR_BLKSIZE; | 934 amrd = (struct amrd_softc *)bp->b_dev->si_drv1; 935 driveno = amrd->amrd_drive - sc->amr_drive; 936 blkcount = (bp->b_bcount + AMR_BLKSIZE - 1) / AMR_BLKSIZE; |
871 872 if ((bp->b_pblkno + blkcount) > sc->amr_drive[driveno].al_size) 873 device_printf(sc->amr_dev, "I/O beyond end of unit (%u,%d > %u)\n", 874 bp->b_pblkno, blkcount, sc->amr_drive[driveno].al_size); 875 876 /* 877 * Build the I/O command. 878 */ --- 8 unchanged lines hidden (view full) --- 887 if (amr_start(ac) != 0) { 888 /* fail the command */ 889 ac->ac_status = AMR_STATUS_WEDGED; 890 amr_completeio(ac); 891 } 892 s = splbio(); 893 } 894 splx(s); | 937 938 if ((bp->b_pblkno + blkcount) > sc->amr_drive[driveno].al_size) 939 device_printf(sc->amr_dev, "I/O beyond end of unit (%u,%d > %u)\n", 940 bp->b_pblkno, blkcount, sc->amr_drive[driveno].al_size); 941 942 /* 943 * Build the I/O command. 944 */ --- 8 unchanged lines hidden (view full) --- 953 if (amr_start(ac) != 0) { 954 /* fail the command */ 955 ac->ac_status = AMR_STATUS_WEDGED; 956 amr_completeio(ac); 957 } 958 s = splbio(); 959 } 960 splx(s); |
961 amr_lock_clr(sc, AMR_LOCK_STARTING); |
|
895} 896 897/******************************************************************************** 898 * Handle completion of an I/O command. 899 */ 900static void 901amr_completeio(struct amr_command *ac) 902{ 903 struct amr_softc *sc = ac->ac_sc; 904 struct buf *bp = (struct buf *)ac->ac_private; | 962} 963 964/******************************************************************************** 965 * Handle completion of an I/O command. 966 */ 967static void 968amr_completeio(struct amr_command *ac) 969{ 970 struct amr_softc *sc = ac->ac_sc; 971 struct buf *bp = (struct buf *)ac->ac_private; |
972 int notify, release; 973 974 notify = 1; 975 release = 1; |
|
905 906 if (ac->ac_status != AMR_STATUS_SUCCESS) { /* could be more verbose here? */ 907 bp->b_error = EIO; 908 bp->b_flags |= B_ERROR; 909 910 switch(ac->ac_status) { 911 /* XXX need more information on I/O error reasons */ | 976 977 if (ac->ac_status != AMR_STATUS_SUCCESS) { /* could be more verbose here? */ 978 bp->b_error = EIO; 979 bp->b_flags |= B_ERROR; 980 981 switch(ac->ac_status) { 982 /* XXX need more information on I/O error reasons */ |
983 case AMR_STATUS_LATE: 984 notify = 0; /* we've already notified the parent */ 985 break; 986 987 case AMR_STATUS_WEDGED: 988 release = 0; /* the command is still outstanding, we can't release */ 989 break; 990 |
|
912 default: 913 device_printf(sc->amr_dev, "I/O error - %x\n", ac->ac_status); 914 amr_printcommand(ac); 915 break; 916 } 917 } | 991 default: 992 device_printf(sc->amr_dev, "I/O error - %x\n", ac->ac_status); 993 amr_printcommand(ac); 994 break; 995 } 996 } |
918 amr_releasecmd(ac); 919 amrd_intr(bp); | 997 if (release) 998 amr_releasecmd(ac); 999 if (notify) 1000 amrd_intr(bp); |
920} 921 922/******************************************************************************** 923 ******************************************************************************** 924 Command Processing 925 ******************************************************************************** 926 ********************************************************************************/ 927 --- 168 unchanged lines hidden (view full) --- 1096 if (ac->ac_flags & AMR_CMD_DATAOUT) 1097 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_POSTWRITE); 1098 1099 bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_dmamap); 1100 } 1101} 1102 1103/******************************************************************************** | 1001} 1002 1003/******************************************************************************** 1004 ******************************************************************************** 1005 Command Processing 1006 ******************************************************************************** 1007 ********************************************************************************/ 1008 --- 168 unchanged lines hidden (view full) --- 1177 if (ac->ac_flags & AMR_CMD_DATAOUT) 1178 bus_dmamap_sync(sc->amr_buffer_dmat, ac->ac_dmamap, BUS_DMASYNC_POSTWRITE); 1179 1180 bus_dmamap_unload(sc->amr_buffer_dmat, ac->ac_dmamap); 1181 } 1182} 1183 1184/******************************************************************************** |
1104 * Take a command and give it to the controller. Take care of any completed 1105 * commands we encouter while waiting. | 1185 * Take a command and give it to the controller. |
1106 */ 1107static int 1108amr_start(struct amr_command *ac) 1109{ 1110 struct amr_softc *sc = ac->ac_sc; | 1186 */ 1187static int 1188amr_start(struct amr_command *ac) 1189{ 1190 struct amr_softc *sc = ac->ac_sc; |
1111 int worked, done, s, i; | 1191 int done, s, i; |
1112 1113 debug("called"); 1114 1115 /* 1116 * Save the slot number so that we can locate this command when complete. 1117 * Note that ident = 0 seems to be special, so we don't use it. 1118 */ 1119 ac->ac_mailbox.mb_ident = ac->ac_slot + 1; 1120 1121 /* set the busy flag when we copy the mailbox in */ 1122 ac->ac_mailbox.mb_busy = 1; 1123 1124 /* set impossible status so that a woken sleeper can tell the command is busy */ 1125 ac->ac_status = AMR_STATUS_BUSY; 1126 | 1192 1193 debug("called"); 1194 1195 /* 1196 * Save the slot number so that we can locate this command when complete. 1197 * Note that ident = 0 seems to be special, so we don't use it. 1198 */ 1199 ac->ac_mailbox.mb_ident = ac->ac_slot + 1; 1200 1201 /* set the busy flag when we copy the mailbox in */ 1202 ac->ac_mailbox.mb_busy = 1; 1203 1204 /* set impossible status so that a woken sleeper can tell the command is busy */ 1205 ac->ac_status = AMR_STATUS_BUSY; 1206 |
1127 /* spin waiting for the mailbox */ | 1207 /* 1208 * Spin waiting for the mailbox, give up after ~1 second. 1209 */ |
1128 debug("wait for mailbox"); | 1210 debug("wait for mailbox"); |
1129 for (i = 10000, done = 0, worked = 0; (i > 0) && !done; i--) { | 1211 for (i = 10000, done = 0; (i > 0) && !done; i--) { |
1130 s = splbio(); 1131 1132 /* is the mailbox free? */ 1133 if (sc->amr_mailbox->mb_busy == 0) { 1134 debug("got mailbox"); 1135 sc->amr_mailbox64->mb64_segment = 0; 1136 bcopy(&ac->ac_mailbox, sc->amr_mailbox, AMR_MBOX_CMDSIZE); 1137 sc->amr_submit_command(sc); 1138 done = 1; 1139 sc->amr_workcount++; 1140 TAILQ_INSERT_TAIL(&sc->amr_work, ac, ac_link); 1141 1142 /* not free, try to clean up while we wait */ 1143 } else { 1144 debug("busy flag %x\n", sc->amr_mailbox->mb_busy); | 1212 s = splbio(); 1213 1214 /* is the mailbox free? */ 1215 if (sc->amr_mailbox->mb_busy == 0) { 1216 debug("got mailbox"); 1217 sc->amr_mailbox64->mb64_segment = 0; 1218 bcopy(&ac->ac_mailbox, sc->amr_mailbox, AMR_MBOX_CMDSIZE); 1219 sc->amr_submit_command(sc); 1220 done = 1; 1221 sc->amr_workcount++; 1222 TAILQ_INSERT_TAIL(&sc->amr_work, ac, ac_link); 1223 1224 /* not free, try to clean up while we wait */ 1225 } else { 1226 debug("busy flag %x\n", sc->amr_mailbox->mb_busy); |
1145 /* try to kill some time being useful */ 1146 if (amr_done(sc)) { 1147 worked = 1; 1148 } else { 1149 DELAY(100); 1150 } | 1227 /* this is somewhat ugly */ 1228 DELAY(100); |
1151 } | 1229 } |
1152 splx(s); | 1230 splx(s); /* drop spl to allow completion interrupts */ |
1153 } 1154 | 1231 } 1232 |
1155 /* do completion processing if we picked anything up */ 1156 if (worked) 1157 amr_complete(sc); 1158 | |
1159 /* command is enqueued? */ 1160 if (done) { 1161 ac->ac_stamp = time_second; 1162 debug("posted command"); 1163 return(0); 1164 } 1165 1166 /* 1167 * The controller wouldn't take the command. Revoke the slot 1168 * that the command was given and return with a bad status. 1169 */ 1170 sc->amr_busycmd[ac->ac_slot] = NULL; 1171 device_printf(sc->amr_dev, "controller wedged (not taking commands)\n"); 1172 ac->ac_status = AMR_STATUS_WEDGED; | 1233 /* command is enqueued? */ 1234 if (done) { 1235 ac->ac_stamp = time_second; 1236 debug("posted command"); 1237 return(0); 1238 } 1239 1240 /* 1241 * The controller wouldn't take the command. Revoke the slot 1242 * that the command was given and return with a bad status. 1243 */ 1244 sc->amr_busycmd[ac->ac_slot] = NULL; 1245 device_printf(sc->amr_dev, "controller wedged (not taking commands)\n"); 1246 ac->ac_status = AMR_STATUS_WEDGED; |
1247 amr_complete(sc); |
|
1173 return(EIO); 1174} 1175 1176/******************************************************************************** 1177 * Extract one or more completed commands from the controller (sc) 1178 * 1179 * Returns nonzero if any commands on the work queue were marked as completed. 1180 */ 1181static int 1182amr_done(struct amr_softc *sc) 1183{ 1184 struct amr_command *ac; 1185 struct amr_mailbox mbox; | 1248 return(EIO); 1249} 1250 1251/******************************************************************************** 1252 * Extract one or more completed commands from the controller (sc) 1253 * 1254 * Returns nonzero if any commands on the work queue were marked as completed. 1255 */ 1256static int 1257amr_done(struct amr_softc *sc) 1258{ 1259 struct amr_command *ac; 1260 struct amr_mailbox mbox; |
1186 int i, idx, result; | 1261 int i, idx, s, result; |
1187 1188 debug("called"); 1189 1190 /* See if there's anything for us to do */ 1191 result = 0; | 1262 1263 debug("called"); 1264 1265 /* See if there's anything for us to do */ 1266 result = 0; |
1192 if (sc->amr_get_work(sc, &mbox)) { 1193 /* iterate over completed commands */ 1194 for (i = 0; i < mbox.mb_nstatus; i++) { 1195 /* get pointer to busy command */ 1196 idx = mbox.mb_completed[i] - 1; 1197 ac = sc->amr_busycmd[idx]; | |
1198 | 1267 |
1199 /* really a busy command? */ 1200 if (ac != NULL) { | 1268 /* loop collecting completed commands */ 1269 s = splbio(); 1270 for (;;) { 1271 /* poll for a completed command's identifier and status */ 1272 if (sc->amr_get_work(sc, &mbox)) { 1273 result = 1; 1274 1275 /* iterate over completed commands in this result */ 1276 for (i = 0; i < mbox.mb_nstatus; i++) { 1277 /* get pointer to busy command */ 1278 idx = mbox.mb_completed[i] - 1; 1279 ac = sc->amr_busycmd[idx]; |
1201 | 1280 |
1202 /* pull the command from the busy index */ 1203 sc->amr_busycmd[idx] = NULL; 1204 sc->amr_busycmdcount--; | 1281 /* really a busy command? */ 1282 if (ac != NULL) { 1283 1284 /* pull the command from the busy index */ 1285 sc->amr_busycmd[idx] = NULL; 1286 sc->amr_busycmdcount--; |
1205 | 1287 |
1206 /* unmap data buffer */ 1207 amr_unmapcmd(ac); | 1288 /* aborted command? */ 1289 if (ac == (struct amr_command *)sc) { 1290 device_printf(sc->amr_dev, "aborted command completed (%d)\n", idx); 1291 sc->amr_busycmd[idx] = NULL; /* free the slot again */ 1292 ac = NULL; |
1208 | 1293 |
1209 /* aborted command? */ 1210 if (ac == (struct amr_command *)sc) { 1211 device_printf(sc->amr_dev, "aborted command completed (%d)\n", idx); 1212 ac = NULL; | 1294 /* wedged command? */ 1295 } else if (ac->ac_status == AMR_STATUS_WEDGED) { 1296 device_printf(sc->amr_dev, "wedged command completed (%d)\n", idx); 1297 ac->ac_status = AMR_STATUS_LATE; |
1213 | 1298 |
1214 /* completed normally, save status */ 1215 } else { 1216 ac->ac_status = mbox.mb_status; 1217 debug("completed command with status %x", mbox.mb_status); | 1299 /* completed normally, save status */ 1300 } else { 1301 ac->ac_status = mbox.mb_status; 1302 debug("completed command with status %x", mbox.mb_status); 1303 } |
1218 } | 1304 } |
1219 result = 1; | |
1220 } | 1305 } |
1306 } else { 1307 break; |
|
1221 } 1222 } | 1308 } 1309 } |
1310 1311 /* if we've completed any commands, try posting some more */ 1312 if (result) 1313 amr_startio(sc); 1314 1315 /* handle completion and timeouts */ 1316 amr_complete(sc); 1317 |
|
1223 return(result); 1224} 1225 1226/******************************************************************************** 1227 * Do completion processing on done commands on (sc) 1228 */ 1229static void 1230amr_complete(struct amr_softc *sc) 1231{ 1232 struct amr_command *ac, *nc; 1233 int s, count; 1234 1235 debug("called"); 1236 | 1318 return(result); 1319} 1320 1321/******************************************************************************** 1322 * Do completion processing on done commands on (sc) 1323 */ 1324static void 1325amr_complete(struct amr_softc *sc) 1326{ 1327 struct amr_command *ac, *nc; 1328 int s, count; 1329 1330 debug("called"); 1331 |
1237 count = 0; | 1332 if (amr_lock_tas(sc, AMR_LOCK_COMPLETING)) 1333 return; |
1238 1239 s = splbio(); | 1334 1335 s = splbio(); |
1336 count = 0; 1337 1338 /* scan the list of busy/done commands */ |
|
1240 ac = TAILQ_FIRST(&sc->amr_work); 1241 while (ac != NULL) { 1242 nc = TAILQ_NEXT(ac, ac_link); 1243 | 1339 ac = TAILQ_FIRST(&sc->amr_work); 1340 while (ac != NULL) { 1341 nc = TAILQ_NEXT(ac, ac_link); 1342 |
1244 /* Skip if command is still active */ | 1343 /* Command has been completed in some fashion */ |
1245 if (ac->ac_status != AMR_STATUS_BUSY) { | 1344 if (ac->ac_status != AMR_STATUS_BUSY) { |
1345 1346 /* unmap the command's data buffer */ 1347 amr_unmapcmd(ac); |
|
1246 1247 /* 1248 * Is there a completion handler? 1249 */ 1250 if (ac->ac_complete != NULL) { 1251 1252 /* remove and give to completion handler */ 1253 TAILQ_REMOVE(&sc->amr_work, ac, ac_link); --- 14 unchanged lines hidden (view full) --- 1268 * Leave it for a polling caller. 1269 */ 1270 } else { 1271 } 1272 } 1273 ac = nc; 1274 } 1275 splx(s); | 1348 1349 /* 1350 * Is there a completion handler? 1351 */ 1352 if (ac->ac_complete != NULL) { 1353 1354 /* remove and give to completion handler */ 1355 TAILQ_REMOVE(&sc->amr_work, ac, ac_link); --- 14 unchanged lines hidden (view full) --- 1370 * Leave it for a polling caller. 1371 */ 1372 } else { 1373 } 1374 } 1375 ac = nc; 1376 } 1377 splx(s); |
1276 1277 /* queue more work if we can */ 1278 amr_startio(sc); | 1378 1379 amr_lock_clr(sc, AMR_LOCK_COMPLETING); |
1279} 1280 1281/******************************************************************************** 1282 ******************************************************************************** 1283 Command Buffer Management 1284 ******************************************************************************** 1285 ********************************************************************************/ 1286 --- 85 unchanged lines hidden (view full) --- 1372 */ 1373static void 1374amr_quartz_submit_command(struct amr_softc *sc) 1375{ 1376 debug("called"); 1377 1378 sc->amr_mailbox->mb_poll = 0; 1379 sc->amr_mailbox->mb_ack = 0; | 1380} 1381 1382/******************************************************************************** 1383 ******************************************************************************** 1384 Command Buffer Management 1385 ******************************************************************************** 1386 ********************************************************************************/ 1387 --- 85 unchanged lines hidden (view full) --- 1473 */ 1474static void 1475amr_quartz_submit_command(struct amr_softc *sc) 1476{ 1477 debug("called"); 1478 1479 sc->amr_mailbox->mb_poll = 0; 1480 sc->amr_mailbox->mb_ack = 0; |
1380 /* XXX write barrier? */ | |
1381 while(AMR_QGET_IDB(sc) & AMR_QIDB_SUBMIT) 1382 ; /* XXX aiee! what if it dies? */ 1383 AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT); 1384} 1385 1386static void 1387amr_std_submit_command(struct amr_softc *sc) 1388{ --- 10 unchanged lines hidden (view full) --- 1399 * save details of the completion in (mbsave) 1400 */ 1401static int 1402amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave) 1403{ 1404 int s, worked; 1405 u_int32_t outd; 1406 | 1481 while(AMR_QGET_IDB(sc) & AMR_QIDB_SUBMIT) 1482 ; /* XXX aiee! what if it dies? */ 1483 AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT); 1484} 1485 1486static void 1487amr_std_submit_command(struct amr_softc *sc) 1488{ --- 10 unchanged lines hidden (view full) --- 1499 * save details of the completion in (mbsave) 1500 */ 1501static int 1502amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave) 1503{ 1504 int s, worked; 1505 u_int32_t outd; 1506 |
1407 debug("called"); | 1507/* debug("called"); */ |
1408 1409 worked = 0; 1410 s = splbio(); 1411 1412 /* work waiting for us? */ 1413 if ((outd = AMR_QGET_ODB(sc)) == AMR_QODB_READY) { 1414 AMR_QPUT_ODB(sc, AMR_QODB_READY); 1415 --- 81 unchanged lines hidden (view full) --- 1497 struct amr_sgentry *sg; 1498 int i; 1499 1500 device_printf(sc->amr_dev, "cmd %x ident %d drive %d\n", 1501 ac->ac_mailbox.mb_command, ac->ac_mailbox.mb_ident, ac->ac_mailbox.mb_drive); 1502 device_printf(sc->amr_dev, "blkcount %d lba %d\n", 1503 ac->ac_mailbox.mb_blkcount, ac->ac_mailbox.mb_lba); 1504 device_printf(sc->amr_dev, "virtaddr %p length %lu\n", ac->ac_data, (unsigned long)ac->ac_length); | 1508 1509 worked = 0; 1510 s = splbio(); 1511 1512 /* work waiting for us? */ 1513 if ((outd = AMR_QGET_ODB(sc)) == AMR_QODB_READY) { 1514 AMR_QPUT_ODB(sc, AMR_QODB_READY); 1515 --- 81 unchanged lines hidden (view full) --- 1597 struct amr_sgentry *sg; 1598 int i; 1599 1600 device_printf(sc->amr_dev, "cmd %x ident %d drive %d\n", 1601 ac->ac_mailbox.mb_command, ac->ac_mailbox.mb_ident, ac->ac_mailbox.mb_drive); 1602 device_printf(sc->amr_dev, "blkcount %d lba %d\n", 1603 ac->ac_mailbox.mb_blkcount, ac->ac_mailbox.mb_lba); 1604 device_printf(sc->amr_dev, "virtaddr %p length %lu\n", ac->ac_data, (unsigned long)ac->ac_length); |
1505 device_printf(sc->amr_dev, "physaddr %08x nsg %d\n", | 1605 device_printf(sc->amr_dev, "sg physaddr %08x nsg %d\n", |
1506 ac->ac_mailbox.mb_physaddr, ac->ac_mailbox.mb_nsgelem); 1507 1508 /* get base address of s/g table */ 1509 sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG); 1510 for (i = 0; i < ac->ac_mailbox.mb_nsgelem; i++, sg++) 1511 device_printf(sc->amr_dev, " %x/%d\n", sg->sg_addr, sg->sg_count); 1512} | 1606 ac->ac_mailbox.mb_physaddr, ac->ac_mailbox.mb_nsgelem); 1607 1608 /* get base address of s/g table */ 1609 sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG); 1610 for (i = 0; i < ac->ac_mailbox.mb_nsgelem; i++, sg++) 1611 device_printf(sc->amr_dev, " %x/%d\n", sg->sg_addr, sg->sg_count); 1612} |
1613 1614/******************************************************************************** 1615 * Print information on all the controllers in the system, useful mostly 1616 * for calling from DDB. 1617 */ 1618void 1619amr_report(void) 1620{ 1621 struct amr_softc *sc; 1622 int i, s; 1623 1624 s = splbio(); 1625 for (i = 0; (sc = devclass_get_softc(amr_devclass, i)) != NULL; i++) { 1626 device_printf(sc->amr_dev, "amr_waitbufs %d amr_busycmdcount %d amr_workcount %d\n", 1627 sc->amr_waitbufs, sc->amr_busycmdcount, sc->amr_workcount); 1628 } 1629} |
|