aac.c (117362) | aac.c (117363) |
---|---|
1/*- 2 * Copyright (c) 2000 Michael Smith 3 * Copyright (c) 2001 Scott Long 4 * Copyright (c) 2000 BSDi 5 * Copyright (c) 2001 Adaptec, Inc. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * | 1/*- 2 * Copyright (c) 2000 Michael Smith 3 * Copyright (c) 2001 Scott Long 4 * Copyright (c) 2000 BSDi 5 * Copyright (c) 2001 Adaptec, Inc. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * |
29 * $FreeBSD: head/sys/dev/aac/aac.c 117362 2003-07-09 19:30:30Z scottl $ | 29 * $FreeBSD: head/sys/dev/aac/aac.c 117363 2003-07-09 21:16:23Z scottl $ |
30 */ 31 32/* 33 * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters. 34 */ 35 36#include "opt_aac.h" 37 --- 24 unchanged lines hidden (view full) --- 62 63static void aac_startup(void *arg); 64static void aac_add_container(struct aac_softc *sc, 65 struct aac_mntinforesp *mir, int f); 66static void aac_get_bus_info(struct aac_softc *sc); 67 68/* Command Processing */ 69static void aac_timeout(struct aac_softc *sc); | 30 */ 31 32/* 33 * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters. 34 */ 35 36#include "opt_aac.h" 37 --- 24 unchanged lines hidden (view full) --- 62 63static void aac_startup(void *arg); 64static void aac_add_container(struct aac_softc *sc, 65 struct aac_mntinforesp *mir, int f); 66static void aac_get_bus_info(struct aac_softc *sc); 67 68/* Command Processing */ 69static void aac_timeout(struct aac_softc *sc); |
70static int aac_start(struct aac_command *cm); | 70static int aac_map_command(struct aac_command *cm); |
71static void aac_complete(void *context, int pending); 72static int aac_bio_command(struct aac_softc *sc, struct aac_command **cmp); 73static void aac_bio_complete(struct aac_command *cm); 74static int aac_wait_command(struct aac_command *cm, int timeout); 75static void aac_command_thread(struct aac_softc *sc); 76 77/* Command Buffer Management */ | 71static void aac_complete(void *context, int pending); 72static int aac_bio_command(struct aac_softc *sc, struct aac_command **cmp); 73static void aac_bio_complete(struct aac_command *cm); 74static int aac_wait_command(struct aac_command *cm, int timeout); 75static void aac_command_thread(struct aac_softc *sc); 76 77/* Command Buffer Management */ |
78static void aac_map_command_sg(void *arg, bus_dma_segment_t *segs, 79 int nseg, int error); |
|
78static void aac_map_command_helper(void *arg, bus_dma_segment_t *segs, 79 int nseg, int error); 80static int aac_alloc_commands(struct aac_softc *sc); 81static void aac_free_commands(struct aac_softc *sc); | 80static void aac_map_command_helper(void *arg, bus_dma_segment_t *segs, 81 int nseg, int error); 82static int aac_alloc_commands(struct aac_softc *sc); 83static void aac_free_commands(struct aac_softc *sc); |
82static void aac_map_command(struct aac_command *cm); | |
83static void aac_unmap_command(struct aac_command *cm); 84 85/* Hardware Interface */ 86static void aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, 87 int error); 88static int aac_check_firmware(struct aac_softc *sc); 89static int aac_init(struct aac_softc *sc); 90static int aac_sync_command(struct aac_softc *sc, u_int32_t command, --- 571 unchanged lines hidden (view full) --- 662 */ 663void 664aac_startio(struct aac_softc *sc) 665{ 666 struct aac_command *cm; 667 668 debug_called(2); 669 | 84static void aac_unmap_command(struct aac_command *cm); 85 86/* Hardware Interface */ 87static void aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, 88 int error); 89static int aac_check_firmware(struct aac_softc *sc); 90static int aac_init(struct aac_softc *sc); 91static int aac_sync_command(struct aac_softc *sc, u_int32_t command, --- 571 unchanged lines hidden (view full) --- 663 */ 664void 665aac_startio(struct aac_softc *sc) 666{ 667 struct aac_command *cm; 668 669 debug_called(2); 670 |
671 if (sc->flags & AAC_QUEUE_FRZN) 672 return; 673 |
|
670 for (;;) { 671 /* 672 * Try to get a command that's been put off for lack of 673 * resources 674 */ 675 cm = aac_dequeue_ready(sc); 676 677 /* 678 * Try to build a command off the bio queue (ignore error 679 * return) 680 */ 681 if (cm == NULL) 682 aac_bio_command(sc, &cm); 683 684 /* nothing to do? */ 685 if (cm == NULL) 686 break; 687 688 /* try to give the command to the controller */ | 674 for (;;) { 675 /* 676 * Try to get a command that's been put off for lack of 677 * resources 678 */ 679 cm = aac_dequeue_ready(sc); 680 681 /* 682 * Try to build a command off the bio queue (ignore error 683 * return) 684 */ 685 if (cm == NULL) 686 aac_bio_command(sc, &cm); 687 688 /* nothing to do? */ 689 if (cm == NULL) 690 break; 691 692 /* try to give the command to the controller */ |
689 if (aac_start(cm) == EBUSY) { | 693 if (aac_map_command(cm) == EBUSY) { |
690 /* put it on the ready queue for later */ 691 aac_requeue_ready(cm); 692 break; 693 } 694 } 695} 696 697/* 698 * Deliver a command to the controller; allocate controller resources at the 699 * last moment when possible. 700 */ 701static int | 694 /* put it on the ready queue for later */ 695 aac_requeue_ready(cm); 696 break; 697 } 698 } 699} 700 701/* 702 * Deliver a command to the controller; allocate controller resources at the 703 * last moment when possible. 704 */ 705static int |
702aac_start(struct aac_command *cm) | 706aac_map_command(struct aac_command *cm) |
703{ 704 struct aac_softc *sc; 705 int error; 706 707 debug_called(2); 708 709 sc = cm->cm_sc; | 707{ 708 struct aac_softc *sc; 709 int error; 710 711 debug_called(2); 712 713 sc = cm->cm_sc; |
714 error = 0; |
|
710 | 715 |
711 /* get the command mapped */ 712 aac_map_command(cm); | 716 /* don't map more than once */ 717 if (cm->cm_flags & AAC_CMD_MAPPED) 718 return (0); |
713 | 719 |
714 /* Fix up the address values in the FIB. Use the command array index 715 * instead of a pointer since these fields are only 32 bits. Shift 716 * the SenderFibAddress over to make room for the fast response bit. 717 */ 718 cm->cm_fib->Header.SenderFibAddress = (cm->cm_index << 1); 719 cm->cm_fib->Header.ReceiverFibAddress = cm->cm_fibphys; 720 721 /* save a pointer to the command for speedy reverse-lookup */ 722 cm->cm_fib->Header.SenderData = cm->cm_index; 723 /* put the FIB on the outbound queue */ 724 error = aac_enqueue_fib(sc, cm->cm_queue, cm); 725 return(error); | 720 if (cm->cm_datalen != 0) { 721 error = bus_dmamap_load(sc->aac_buffer_dmat, cm->cm_datamap, 722 cm->cm_data, cm->cm_datalen, 723 aac_map_command_sg, cm, 0); 724 if (error == EINPROGRESS) { 725 debug(1, "freezing queue\n"); 726 sc->flags |= AAC_QUEUE_FRZN; 727 error = 0; 728 } 729 } 730 return (error); |
726} 727 728/* 729 * Handle notification of one or more FIBs coming from the controller. 730 */ 731static void 732aac_command_thread(struct aac_softc *sc) 733{ --- 120 unchanged lines hidden (view full) --- 854 cm->cm_complete(cm); 855 } else { 856 /* assume that someone is sleeping on this command */ 857 wakeup(cm); 858 } 859 } 860 861 /* see if we can start some more I/O */ | 731} 732 733/* 734 * Handle notification of one or more FIBs coming from the controller. 735 */ 736static void 737aac_command_thread(struct aac_softc *sc) 738{ --- 120 unchanged lines hidden (view full) --- 859 cm->cm_complete(cm); 860 } else { 861 /* assume that someone is sleeping on this command */ 862 wakeup(cm); 863 } 864 } 865 866 /* see if we can start some more I/O */ |
867 sc->flags &= ~AAC_QUEUE_FRZN; |
|
862 aac_startio(sc); 863 864 AAC_LOCK_RELEASE(&sc->aac_io_lock); 865} 866 867/* 868 * Handle a bio submitted from a disk device. 869 */ --- 283 unchanged lines hidden (view full) --- 1153 if (bus_dmamem_alloc(sc->aac_fib_dmat, (void **)&fm->aac_fibs, 1154 BUS_DMA_NOWAIT, &fm->aac_fibmap)) { 1155 device_printf(sc->aac_dev, 1156 "Not enough contiguous memory available.\n"); 1157 free(fm, M_AACBUF); 1158 return (ENOMEM); 1159 } 1160 | 868 aac_startio(sc); 869 870 AAC_LOCK_RELEASE(&sc->aac_io_lock); 871} 872 873/* 874 * Handle a bio submitted from a disk device. 875 */ --- 283 unchanged lines hidden (view full) --- 1159 if (bus_dmamem_alloc(sc->aac_fib_dmat, (void **)&fm->aac_fibs, 1160 BUS_DMA_NOWAIT, &fm->aac_fibmap)) { 1161 device_printf(sc->aac_dev, 1162 "Not enough contiguous memory available.\n"); 1163 free(fm, M_AACBUF); 1164 return (ENOMEM); 1165 } 1166 |
1161 bus_dmamap_load(sc->aac_fib_dmat, fm->aac_fibmap, fm->aac_fibs, 1162 AAC_FIB_COUNT * sizeof(struct aac_fib), 1163 aac_map_command_helper, &fibphys, 0); | 1167 /* Ignore errors since this doesn't bounce */ 1168 (void)bus_dmamap_load(sc->aac_fib_dmat, fm->aac_fibmap, fm->aac_fibs, 1169 AAC_FIB_COUNT * sizeof(struct aac_fib), 1170 aac_map_command_helper, &fibphys, 0); |
1164 1165 /* initialise constant fields in the command structure */ 1166 bzero(fm->aac_fibs, AAC_FIB_COUNT * sizeof(struct aac_fib)); 1167 for (i = 0; i < AAC_FIB_COUNT; i++) { 1168 cm = sc->aac_commands + sc->total_fibs; 1169 fm->aac_commands = cm; 1170 cm->cm_sc = sc; 1171 cm->cm_fib = fm->aac_fibs + i; --- 50 unchanged lines hidden (view full) --- 1222} 1223 1224/* 1225 * Command-mapping helper function - populate this command's s/g table. 1226 */ 1227static void 1228aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1229{ | 1171 1172 /* initialise constant fields in the command structure */ 1173 bzero(fm->aac_fibs, AAC_FIB_COUNT * sizeof(struct aac_fib)); 1174 for (i = 0; i < AAC_FIB_COUNT; i++) { 1175 cm = sc->aac_commands + sc->total_fibs; 1176 fm->aac_commands = cm; 1177 cm->cm_sc = sc; 1178 cm->cm_fib = fm->aac_fibs + i; --- 50 unchanged lines hidden (view full) --- 1229} 1230 1231/* 1232 * Command-mapping helper function - populate this command's s/g table. 1233 */ 1234static void 1235aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1236{ |
1237 struct aac_softc *sc; |
|
1230 struct aac_command *cm; 1231 struct aac_fib *fib; 1232 int i; 1233 1234 debug_called(3); 1235 1236 cm = (struct aac_command *)arg; | 1238 struct aac_command *cm; 1239 struct aac_fib *fib; 1240 int i; 1241 1242 debug_called(3); 1243 1244 cm = (struct aac_command *)arg; |
1245 sc = cm->cm_sc; |
|
1237 fib = cm->cm_fib; 1238 1239 /* copy into the FIB */ 1240 if (cm->cm_sgtable != NULL) { 1241 if ((cm->cm_sc->flags & AAC_FLAGS_SG_64BIT) == 0) { 1242 struct aac_sg_table *sg; 1243 sg = cm->cm_sgtable; 1244 sg->SgCount = nseg; --- 10 unchanged lines hidden (view full) --- 1255 for (i = 0; i < nseg; i++) { 1256 sg->SgEntry64[i].SgAddress = segs[i].ds_addr; 1257 sg->SgEntry64[i].SgByteCount = segs[i].ds_len; 1258 } 1259 /* update the FIB size for the s/g count */ 1260 fib->Header.Size += nseg*sizeof(struct aac_sg_entry64); 1261 } 1262 } | 1246 fib = cm->cm_fib; 1247 1248 /* copy into the FIB */ 1249 if (cm->cm_sgtable != NULL) { 1250 if ((cm->cm_sc->flags & AAC_FLAGS_SG_64BIT) == 0) { 1251 struct aac_sg_table *sg; 1252 sg = cm->cm_sgtable; 1253 sg->SgCount = nseg; --- 10 unchanged lines hidden (view full) --- 1264 for (i = 0; i < nseg; i++) { 1265 sg->SgEntry64[i].SgAddress = segs[i].ds_addr; 1266 sg->SgEntry64[i].SgByteCount = segs[i].ds_len; 1267 } 1268 /* update the FIB size for the s/g count */ 1269 fib->Header.Size += nseg*sizeof(struct aac_sg_entry64); 1270 } 1271 } |
1263} | |
1264 | 1272 |
1265/* 1266 * Map a command into controller-visible space. 1267 */ 1268static void 1269aac_map_command(struct aac_command *cm) 1270{ 1271 struct aac_softc *sc; | 1273 /* Fix up the address values in the FIB. Use the command array index 1274 * instead of a pointer since these fields are only 32 bits. Shift 1275 * the SenderFibAddress over to make room for the fast response bit. 1276 */ 1277 cm->cm_fib->Header.SenderFibAddress = (cm->cm_index << 1); 1278 cm->cm_fib->Header.ReceiverFibAddress = cm->cm_fibphys; |
1272 | 1279 |
1273 debug_called(2); | 1280 /* save a pointer to the command for speedy reverse-lookup */ 1281 cm->cm_fib->Header.SenderData = cm->cm_index; |
1274 | 1282 |
1275 sc = cm->cm_sc; | 1283 if (cm->cm_flags & AAC_CMD_DATAIN) 1284 bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, 1285 BUS_DMASYNC_PREREAD); 1286 if (cm->cm_flags & AAC_CMD_DATAOUT) 1287 bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, 1288 BUS_DMASYNC_PREWRITE); 1289 cm->cm_flags |= AAC_CMD_MAPPED; |
1276 | 1290 |
1277 /* don't map more than once */ 1278 if (cm->cm_flags & AAC_CMD_MAPPED) 1279 return; | 1291 /* put the FIB on the outbound queue */ 1292 if (aac_enqueue_fib(sc, cm->cm_queue, cm) == EBUSY) 1293 aac_requeue_ready(cm); |
1280 | 1294 |
1281 if (cm->cm_datalen != 0) { 1282 bus_dmamap_load(sc->aac_buffer_dmat, cm->cm_datamap, 1283 cm->cm_data, cm->cm_datalen, 1284 aac_map_command_sg, cm, 0); 1285 1286 if (cm->cm_flags & AAC_CMD_DATAIN) 1287 bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, 1288 BUS_DMASYNC_PREREAD); 1289 if (cm->cm_flags & AAC_CMD_DATAOUT) 1290 bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap, 1291 BUS_DMASYNC_PREWRITE); 1292 } 1293 cm->cm_flags |= AAC_CMD_MAPPED; | 1295 return; |
1294} 1295 1296/* 1297 * Unmap a command from controller-visible space. 1298 */ 1299static void 1300aac_unmap_command(struct aac_command *cm) 1301{ --- 79 unchanged lines hidden (view full) --- 1381 options = AAC_GET_MAILBOX(sc, 1); 1382 sc->supported_options = options; 1383 1384 if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 && 1385 (sc->flags & AAC_FLAGS_NO4GB) == 0) 1386 sc->flags |= AAC_FLAGS_4GB_WINDOW; 1387 if (options & AAC_SUPPORTED_NONDASD) 1388 sc->flags |= AAC_FLAGS_ENABLE_CAM; | 1296} 1297 1298/* 1299 * Unmap a command from controller-visible space. 1300 */ 1301static void 1302aac_unmap_command(struct aac_command *cm) 1303{ --- 79 unchanged lines hidden (view full) --- 1383 options = AAC_GET_MAILBOX(sc, 1); 1384 sc->supported_options = options; 1385 1386 if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 && 1387 (sc->flags & AAC_FLAGS_NO4GB) == 0) 1388 sc->flags |= AAC_FLAGS_4GB_WINDOW; 1389 if (options & AAC_SUPPORTED_NONDASD) 1390 sc->flags |= AAC_FLAGS_ENABLE_CAM; |
1389 if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0 && (sizeof(bus_addr_t) > 4)) { | 1391 if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0 1392 && (sizeof(bus_addr_t) > 4)) { |
1390 device_printf(sc->aac_dev, "Enabling 64-bit address support\n"); 1391 sc->flags |= AAC_FLAGS_SG_64BIT; 1392 } 1393 1394 /* Check for broken hardware that does a lower number of commands */ 1395 if ((sc->flags & AAC_FLAGS_256FIBS) == 0) 1396 sc->aac_max_fibs = AAC_MAX_FIBS; 1397 else --- 107 unchanged lines hidden (view full) --- 1505 } 1506 1507 /* 1508 * Work around a bug in the 2120 and 2200 that cannot DMA commands 1509 * below address 8192 in physical memory. 1510 * XXX If the padding is not needed, can it be put to use instead 1511 * of ignored? 1512 */ | 1393 device_printf(sc->aac_dev, "Enabling 64-bit address support\n"); 1394 sc->flags |= AAC_FLAGS_SG_64BIT; 1395 } 1396 1397 /* Check for broken hardware that does a lower number of commands */ 1398 if ((sc->flags & AAC_FLAGS_256FIBS) == 0) 1399 sc->aac_max_fibs = AAC_MAX_FIBS; 1400 else --- 107 unchanged lines hidden (view full) --- 1508 } 1509 1510 /* 1511 * Work around a bug in the 2120 and 2200 that cannot DMA commands 1512 * below address 8192 in physical memory. 1513 * XXX If the padding is not needed, can it be put to use instead 1514 * of ignored? 1515 */ |
1513 bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap, | 1516 (void)bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap, |
1514 sc->aac_common, 8192 + sizeof(*sc->aac_common), 1515 aac_common_map, sc, 0); 1516 1517 if (sc->aac_common_busaddr < 8192) { 1518 (uint8_t *)sc->aac_common += 8192; 1519 sc->aac_common_busaddr += 8192; 1520 } 1521 bzero(sc->aac_common, sizeof(*sc->aac_common)); --- 1461 unchanged lines hidden --- | 1517 sc->aac_common, 8192 + sizeof(*sc->aac_common), 1518 aac_common_map, sc, 0); 1519 1520 if (sc->aac_common_busaddr < 8192) { 1521 (uint8_t *)sc->aac_common += 8192; 1522 sc->aac_common_busaddr += 8192; 1523 } 1524 bzero(sc->aac_common, sizeof(*sc->aac_common)); --- 1461 unchanged lines hidden --- |