1 /*- 2 * Copyright (c) 2002 Adaptec Inc. 3 * All rights reserved. 4 * 5 * Written by: David Jeffery 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 32 #include <dev/ips/ips.h> 33 34 /* 35 * This is an interrupt callback. It is called from 36 * interrupt context when the adapter has completed the 37 * command. This very generic callback simply stores 38 * the command's return value in command->arg and wake's 39 * up anyone waiting on the command. 40 */ 41 static void ips_wakeup_callback(ips_command_t *command) 42 { 43 ips_cmd_status_t *status; 44 status = command->arg; 45 status->value = command->status.value; 46 bus_dmamap_sync(command->sc->command_dmatag, command->command_dmamap, 47 BUS_DMASYNC_POSTWRITE); 48 mtx_lock(&command->sc->cmd_mtx); 49 wakeup(status); 50 mtx_unlock(&command->sc->cmd_mtx); 51 } 52 /* Below are a series of functions for sending an IO request 53 * to the adapter. The flow order is: start, send, callback, finish. 54 * The caller must have already assembled an iorequest struct to hold 55 * the details of the IO request. */ 56 static void ips_io_request_finish(ips_command_t *command) 57 { 58 59 struct bio *iobuf = command->arg; 60 if(ips_read_request(iobuf)) { 61 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 62 BUS_DMASYNC_POSTREAD); 63 } else { 64 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 65 BUS_DMASYNC_POSTWRITE); 66 } 67 bus_dmamap_unload(command->data_dmatag, command->data_dmamap); 68 bus_dmamap_destroy(command->data_dmatag, command->data_dmamap); 69 if(COMMAND_ERROR(&command->status)){ 70 iobuf->bio_flags |=BIO_ERROR; 71 iobuf->bio_error = EIO; 72 } 73 ips_insert_free_cmd(command->sc, command); 74 ipsd_finish(iobuf); 75 } 76 77 static void ips_io_request_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error) 78 { 79 ips_softc_t *sc; 80 ips_command_t *command = cmdptr; 81 ips_sg_element_t *sg_list; 82 ips_io_cmd *command_struct; 83 struct bio *iobuf = command->arg; 84 int i, length = 0; 85 u_int8_t cmdtype; 86 87 sc = command->sc; 88 if(error){ 89 printf("ips: error = %d in ips_sg_request_callback\n", error); 90 bus_dmamap_unload(command->data_dmatag, command->data_dmamap); 91 bus_dmamap_destroy(command->data_dmatag, command->data_dmamap); 92 iobuf->bio_flags |= BIO_ERROR; 93 iobuf->bio_error = ENOMEM; 94 ips_insert_free_cmd(sc, command); 95 ipsd_finish(iobuf); 96 return; 97 } 98 command_struct = (ips_io_cmd *)command->command_buffer; 99 command_struct->id = command->id; 100 command_struct->drivenum = (uint32_t)iobuf->bio_driver1; 101 if(segnum != 1){ 102 if(ips_read_request(iobuf)) 103 cmdtype = IPS_SG_READ_CMD; 104 else 105 cmdtype = IPS_SG_WRITE_CMD; 106 command_struct->segnum = segnum; 107 sg_list = (ips_sg_element_t *)((u_int8_t *) 108 command->command_buffer + IPS_COMMAND_LEN); 109 for(i = 0; i < segnum; i++){ 110 sg_list[i].addr = segments[i].ds_addr; 111 sg_list[i].len = segments[i].ds_len; 112 length += segments[i].ds_len; 113 } 114 command_struct->buffaddr = 115 (u_int32_t)command->command_phys_addr + IPS_COMMAND_LEN; 116 } else { 117 if(ips_read_request(iobuf)) 118 cmdtype = IPS_READ_CMD; 119 else 120 cmdtype = IPS_WRITE_CMD; 121 command_struct->buffaddr = segments[0].ds_addr; 122 length = segments[0].ds_len; 123 } 124 command_struct->command = cmdtype; 125 command_struct->lba = iobuf->bio_pblkno; 126 length = (length + IPS_BLKSIZE - 1)/IPS_BLKSIZE; 127 command_struct->length = length; 128 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 129 BUS_DMASYNC_PREWRITE); 130 if(ips_read_request(iobuf)) { 131 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 132 BUS_DMASYNC_PREREAD); 133 } else { 134 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 135 BUS_DMASYNC_PREWRITE); 136 } 137 PRINTF(10, "ips test: command id: %d segments: %d blkno: %lld " 138 "pblkno: %lld length: %d, ds_len: %d\n", command->id, segnum, 139 iobuf->bio_blkno, iobuf->bio_pblkno, 140 length, segments[0].ds_len); 141 142 sc->ips_issue_cmd(command); 143 return; 144 } 145 146 static int ips_send_io_request(ips_command_t *command) 147 { 148 ips_softc_t *sc = command->sc; 149 struct bio *iobuf = command->arg; 150 command->data_dmatag = sc->sg_dmatag; 151 if(bus_dmamap_create(command->data_dmatag, 0, &command->data_dmamap)){ 152 device_printf(sc->dev, "dmamap failed\n"); 153 iobuf->bio_flags |= BIO_ERROR; 154 iobuf->bio_error = ENOMEM; 155 ips_insert_free_cmd(sc, command); 156 ipsd_finish(iobuf); 157 return 0; 158 } 159 command->callback = ips_io_request_finish; 160 PRINTF(10, "ips test: : bcount %ld\n", iobuf->bio_bcount); 161 bus_dmamap_load(command->data_dmatag, command->data_dmamap, 162 iobuf->bio_data, iobuf->bio_bcount, 163 ips_io_request_callback, command, 0); 164 return 0; 165 } 166 167 void ips_start_io_request(ips_softc_t *sc, struct bio *iobuf) 168 { 169 if(ips_get_free_cmd(sc, ips_send_io_request, iobuf, 0)){ 170 device_printf(sc->dev, "no mem for command slots!\n"); 171 iobuf->bio_flags |= BIO_ERROR; 172 iobuf->bio_error = ENOMEM; 173 ipsd_finish(iobuf); 174 return; 175 } 176 return; 177 } 178 179 /* Below are a series of functions for sending an adapter info request 180 * to the adapter. The flow order is: get, send, callback. It uses 181 * the generic finish callback at the top of this file. 182 * This can be used to get configuration/status info from the card */ 183 static void ips_adapter_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error) 184 { 185 ips_softc_t *sc; 186 ips_command_t *command = cmdptr; 187 ips_adapter_info_cmd *command_struct; 188 sc = command->sc; 189 if(error){ 190 ips_cmd_status_t * status = command->arg; 191 status->value = IPS_ERROR_STATUS; /* a lovely error value */ 192 ips_insert_free_cmd(sc, command); 193 printf("ips: error = %d in ips_get_adapter_info\n", error); 194 return; 195 } 196 command_struct = (ips_adapter_info_cmd *)command->command_buffer; 197 command_struct->command = IPS_ADAPTER_INFO_CMD; 198 command_struct->id = command->id; 199 command_struct->buffaddr = segments[0].ds_addr; 200 201 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 202 BUS_DMASYNC_PREWRITE); 203 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 204 BUS_DMASYNC_PREREAD); 205 sc->ips_issue_cmd(command); 206 } 207 208 209 210 static int ips_send_adapter_info_cmd(ips_command_t *command) 211 { 212 int error = 0; 213 ips_softc_t *sc = command->sc; 214 ips_cmd_status_t *status = command->arg; 215 216 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag, 217 /* alignemnt */ 1, 218 /* boundary */ 0, 219 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 220 /* highaddr */ BUS_SPACE_MAXADDR, 221 /* filter */ NULL, 222 /* filterarg */ NULL, 223 /* maxsize */ IPS_ADAPTER_INFO_LEN, 224 /* numsegs */ 1, 225 /* maxsegsize*/ IPS_ADAPTER_INFO_LEN, 226 /* flags */ 0, 227 &command->data_dmatag) != 0) { 228 printf("ips: can't alloc dma tag for adapter status\n"); 229 error = ENOMEM; 230 goto exit; 231 } 232 if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 233 BUS_DMA_NOWAIT, &command->data_dmamap)){ 234 error = ENOMEM; 235 goto exit; 236 } 237 command->callback = ips_wakeup_callback; 238 mtx_lock(&sc->cmd_mtx); 239 bus_dmamap_load(command->data_dmatag, command->data_dmamap, 240 command->data_buffer,IPS_ADAPTER_INFO_LEN, 241 ips_adapter_info_callback, command, BUS_DMA_NOWAIT); 242 243 if ((status->value == IPS_ERROR_STATUS) || 244 (msleep(status, &sc->cmd_mtx, 0, "ips", 30*hz) == EWOULDBLOCK)) 245 error = ETIMEDOUT; 246 mtx_unlock(&sc->cmd_mtx); 247 248 if (error == 0) { 249 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 250 BUS_DMASYNC_POSTREAD); 251 memcpy(&(sc->adapter_info), command->data_buffer, 252 IPS_ADAPTER_INFO_LEN); 253 } 254 bus_dmamap_unload(command->data_dmatag, command->data_dmamap); 255 256 exit: 257 /* I suppose I should clean up my memory allocations */ 258 bus_dmamem_free(command->data_dmatag, command->data_buffer, 259 command->data_dmamap); 260 bus_dma_tag_destroy(command->data_dmatag); 261 ips_insert_free_cmd(sc, command); 262 return error; 263 } 264 265 int ips_get_adapter_info(ips_softc_t *sc) 266 { 267 int error = 0; 268 ips_cmd_status_t *status; 269 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT); 270 if(!status) 271 return ENOMEM; 272 if(ips_get_free_cmd(sc, ips_send_adapter_info_cmd, status, 273 IPS_NOWAIT_FLAG) > 0){ 274 device_printf(sc->dev, "unable to get adapter configuration\n"); 275 free(status, M_DEVBUF); 276 return ENXIO; 277 } 278 if(COMMAND_ERROR(status)){ 279 error = ENXIO; 280 } 281 free(status, M_DEVBUF); 282 return error; 283 } 284 285 /* Below are a series of functions for sending a drive info request 286 * to the adapter. The flow order is: get, send, callback. It uses 287 * the generic finish callback at the top of this file. 288 * This can be used to get drive status info from the card */ 289 static void ips_drive_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error) 290 { 291 ips_softc_t *sc; 292 ips_command_t *command = cmdptr; 293 ips_drive_cmd *command_struct; 294 sc = command->sc; 295 if(error){ 296 ips_cmd_status_t * status = command->arg; 297 status->value = IPS_ERROR_STATUS; 298 ips_insert_free_cmd(sc, command); 299 printf("ips: error = %d in ips_get_drive_info\n", error); 300 return; 301 } 302 command_struct = (ips_drive_cmd *)command->command_buffer; 303 command_struct->command = IPS_DRIVE_INFO_CMD; 304 command_struct->id = command->id; 305 command_struct->buffaddr = segments[0].ds_addr; 306 307 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 308 BUS_DMASYNC_PREWRITE); 309 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 310 BUS_DMASYNC_PREREAD); 311 sc->ips_issue_cmd(command); 312 } 313 314 static int ips_send_drive_info_cmd(ips_command_t *command) 315 { 316 int error = 0; 317 ips_softc_t *sc = command->sc; 318 ips_cmd_status_t *status = command->arg; 319 ips_drive_info_t *driveinfo; 320 321 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag, 322 /* alignemnt */ 1, 323 /* boundary */ 0, 324 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 325 /* highaddr */ BUS_SPACE_MAXADDR, 326 /* filter */ NULL, 327 /* filterarg */ NULL, 328 /* maxsize */ IPS_DRIVE_INFO_LEN, 329 /* numsegs */ 1, 330 /* maxsegsize*/ IPS_DRIVE_INFO_LEN, 331 /* flags */ 0, 332 &command->data_dmatag) != 0) { 333 printf("ips: can't alloc dma tag for drive status\n"); 334 error = ENOMEM; 335 goto exit; 336 } 337 if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 338 BUS_DMA_NOWAIT, &command->data_dmamap)){ 339 error = ENOMEM; 340 goto exit; 341 } 342 command->callback = ips_wakeup_callback; 343 mtx_lock(&sc->cmd_mtx); 344 bus_dmamap_load(command->data_dmatag, command->data_dmamap, 345 command->data_buffer,IPS_DRIVE_INFO_LEN, 346 ips_drive_info_callback, command, BUS_DMA_NOWAIT); 347 if ((status->value == IPS_ERROR_STATUS) || 348 (msleep(status, &sc->cmd_mtx, 0, "ips", 10*hz) == EWOULDBLOCK)) 349 error = ETIMEDOUT; 350 mtx_unlock(&sc->cmd_mtx); 351 352 if (error == 0) { 353 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 354 BUS_DMASYNC_POSTREAD); 355 driveinfo = command->data_buffer; 356 memcpy(sc->drives, driveinfo->drives, sizeof(ips_drive_t) * 8); 357 sc->drivecount = driveinfo->drivecount; 358 device_printf(sc->dev, "logical drives: %d\n",sc->drivecount); 359 } 360 bus_dmamap_unload(command->data_dmatag, command->data_dmamap); 361 362 exit: 363 /* I suppose I should clean up my memory allocations */ 364 bus_dmamem_free(command->data_dmatag, command->data_buffer, 365 command->data_dmamap); 366 bus_dma_tag_destroy(command->data_dmatag); 367 ips_insert_free_cmd(sc, command); 368 return error; 369 370 } 371 int ips_get_drive_info(ips_softc_t *sc) 372 { 373 int error = 0; 374 ips_cmd_status_t *status; 375 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT); 376 if(!status) 377 return ENOMEM; 378 if(ips_get_free_cmd(sc, ips_send_drive_info_cmd, status, 379 IPS_NOWAIT_FLAG) > 0){ 380 free(status, M_DEVBUF); 381 device_printf(sc->dev, "unable to get drive configuration\n"); 382 return ENXIO; 383 } 384 if(COMMAND_ERROR(status)){ 385 error = ENXIO; 386 } 387 free(status, M_DEVBUF); 388 return error; 389 } 390 391 /* Below is a pair of functions for making sure data is safely 392 * on disk by flushing the adapter's cache. */ 393 static int ips_send_flush_cache_cmd(ips_command_t *command) 394 { 395 ips_softc_t *sc = command->sc; 396 ips_cmd_status_t *status = command->arg; 397 ips_generic_cmd *command_struct; 398 399 PRINTF(10,"ips test: got a command, building flush command\n"); 400 command->callback = ips_wakeup_callback; 401 command_struct = (ips_generic_cmd *)command->command_buffer; 402 command_struct->command = IPS_CACHE_FLUSH_CMD; 403 command_struct->id = command->id; 404 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 405 BUS_DMASYNC_PREWRITE); 406 mtx_lock(&sc->cmd_mtx); 407 sc->ips_issue_cmd(command); 408 if (status->value != IPS_ERROR_STATUS) 409 msleep(status, &sc->cmd_mtx, 0, "flush2", 0); 410 mtx_unlock(&sc->cmd_mtx); 411 ips_insert_free_cmd(sc, command); 412 return 0; 413 } 414 415 int ips_flush_cache(ips_softc_t *sc) 416 { 417 ips_cmd_status_t *status; 418 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT); 419 if(!status) 420 return ENOMEM; 421 device_printf(sc->dev, "flushing cache\n"); 422 if(ips_get_free_cmd(sc, ips_send_flush_cache_cmd, status, 423 IPS_NOWAIT_FLAG)){ 424 free(status, M_DEVBUF); 425 device_printf(sc->dev, "ERROR: unable to get a command! can't flush cache!\n"); 426 } 427 if(COMMAND_ERROR(status)){ 428 device_printf(sc->dev, "ERROR: cache flush command failed!\n"); 429 } 430 free(status, M_DEVBUF); 431 return 0; 432 } 433 434 static void ips_write_nvram(ips_command_t *command){ 435 ips_softc_t *sc = command->sc; 436 ips_rw_nvram_cmd *command_struct; 437 ips_nvram_page5 *nvram; 438 439 /*FIXME check for error */ 440 command->callback = ips_wakeup_callback; 441 command_struct = (ips_rw_nvram_cmd *)command->command_buffer; 442 command_struct->command = IPS_RW_NVRAM_CMD; 443 command_struct->id = command->id; 444 command_struct->pagenum = 5; 445 command_struct->rw = 1; /*write*/ 446 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 447 BUS_DMASYNC_POSTREAD); 448 nvram = command->data_buffer; 449 strncpy(nvram->driver_high, IPS_VERSION_MAJOR, 4); 450 strncpy(nvram->driver_low, IPS_VERSION_MINOR, 4); 451 nvram->operating_system = IPS_OS_FREEBSD; 452 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 453 BUS_DMASYNC_PREWRITE); 454 sc->ips_issue_cmd(command); 455 } 456 457 static void ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error) 458 { 459 ips_softc_t *sc; 460 ips_command_t *command = cmdptr; 461 ips_rw_nvram_cmd *command_struct; 462 sc = command->sc; 463 if(error){ 464 ips_cmd_status_t * status = command->arg; 465 status->value = IPS_ERROR_STATUS; 466 ips_insert_free_cmd(sc, command); 467 printf("ips: error = %d in ips_read_nvram_callback\n", error); 468 return; 469 } 470 command_struct = (ips_rw_nvram_cmd *)command->command_buffer; 471 command_struct->command = IPS_RW_NVRAM_CMD; 472 command_struct->id = command->id; 473 command_struct->pagenum = 5; 474 command_struct->rw = 0; 475 command_struct->buffaddr = segments[0].ds_addr; 476 477 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 478 BUS_DMASYNC_PREWRITE); 479 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 480 BUS_DMASYNC_PREREAD); 481 sc->ips_issue_cmd(command); 482 } 483 484 static int ips_read_nvram(ips_command_t *command){ 485 int error = 0; 486 ips_softc_t *sc = command->sc; 487 ips_cmd_status_t *status = command->arg; 488 489 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag, 490 /* alignemnt */ 1, 491 /* boundary */ 0, 492 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 493 /* highaddr */ BUS_SPACE_MAXADDR, 494 /* filter */ NULL, 495 /* filterarg */ NULL, 496 /* maxsize */ IPS_NVRAM_PAGE_SIZE, 497 /* numsegs */ 1, 498 /* maxsegsize*/ IPS_NVRAM_PAGE_SIZE, 499 /* flags */ 0, 500 &command->data_dmatag) != 0) { 501 printf("ips: can't alloc dma tag for nvram\n"); 502 error = ENOMEM; 503 goto exit; 504 } 505 if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 506 BUS_DMA_NOWAIT, &command->data_dmamap)){ 507 error = ENOMEM; 508 goto exit; 509 } 510 command->callback = ips_write_nvram; 511 mtx_lock(&sc->cmd_mtx); 512 bus_dmamap_load(command->data_dmatag, command->data_dmamap, 513 command->data_buffer,IPS_NVRAM_PAGE_SIZE, 514 ips_read_nvram_callback, command, BUS_DMA_NOWAIT); 515 if ((status->value == IPS_ERROR_STATUS) || 516 (msleep(status, &sc->cmd_mtx, 0, "ips", 0) == EWOULDBLOCK)) 517 error = ETIMEDOUT; 518 mtx_unlock(&sc->cmd_mtx); 519 520 if (error == 0) { 521 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 522 BUS_DMASYNC_POSTWRITE); 523 } 524 bus_dmamap_unload(command->data_dmatag, command->data_dmamap); 525 526 exit: 527 bus_dmamem_free(command->data_dmatag, command->data_buffer, 528 command->data_dmamap); 529 bus_dma_tag_destroy(command->data_dmatag); 530 ips_insert_free_cmd(sc, command); 531 return error; 532 } 533 534 int ips_update_nvram(ips_softc_t *sc) 535 { 536 ips_cmd_status_t *status; 537 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT); 538 if(!status) 539 return ENOMEM; 540 if(ips_get_free_cmd(sc, ips_read_nvram, status, IPS_NOWAIT_FLAG)){ 541 free(status, M_DEVBUF); 542 device_printf(sc->dev, "ERROR: unable to get a command! can't update nvram\n"); 543 return 1; 544 } 545 if(COMMAND_ERROR(status)){ 546 device_printf(sc->dev, "ERROR: nvram update command failed!\n"); 547 } 548 free(status, M_DEVBUF); 549 return 0; 550 551 552 } 553 554 555 static int ips_send_config_sync_cmd(ips_command_t *command) 556 { 557 ips_softc_t *sc = command->sc; 558 ips_cmd_status_t *status = command->arg; 559 ips_generic_cmd *command_struct; 560 561 PRINTF(10,"ips test: got a command, building flush command\n"); 562 command->callback = ips_wakeup_callback; 563 command_struct = (ips_generic_cmd *)command->command_buffer; 564 command_struct->command = IPS_CONFIG_SYNC_CMD; 565 command_struct->id = command->id; 566 command_struct->reserve2 = IPS_POCL; 567 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 568 BUS_DMASYNC_PREWRITE); 569 mtx_lock(&sc->cmd_mtx); 570 sc->ips_issue_cmd(command); 571 if (status->value != IPS_ERROR_STATUS) 572 msleep(status, &sc->cmd_mtx, 0, "ipssyn", 0); 573 mtx_unlock(&sc->cmd_mtx); 574 ips_insert_free_cmd(sc, command); 575 return 0; 576 } 577 578 static int ips_send_error_table_cmd(ips_command_t *command) 579 { 580 ips_softc_t *sc = command->sc; 581 ips_cmd_status_t *status = command->arg; 582 ips_generic_cmd *command_struct; 583 584 PRINTF(10,"ips test: got a command, building errortable command\n"); 585 command->callback = ips_wakeup_callback; 586 command_struct = (ips_generic_cmd *)command->command_buffer; 587 command_struct->command = IPS_ERROR_TABLE_CMD; 588 command_struct->id = command->id; 589 command_struct->reserve2 = IPS_CSL; 590 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 591 BUS_DMASYNC_PREWRITE); 592 mtx_lock(&sc->cmd_mtx); 593 sc->ips_issue_cmd(command); 594 if (status->value != IPS_ERROR_STATUS) 595 msleep(status, &sc->cmd_mtx, 0, "ipsetc", 0); 596 mtx_unlock(&sc->cmd_mtx); 597 ips_insert_free_cmd(sc, command); 598 return 0; 599 } 600 601 602 int ips_clear_adapter(ips_softc_t *sc) 603 { 604 ips_cmd_status_t *status; 605 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT); 606 if(!status) 607 return ENOMEM; 608 device_printf(sc->dev, "syncing config\n"); 609 if(ips_get_free_cmd(sc, ips_send_config_sync_cmd, status, 610 IPS_NOWAIT_FLAG)){ 611 free(status, M_DEVBUF); 612 device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n"); 613 return 1; 614 } 615 if(COMMAND_ERROR(status)){ 616 free(status, M_DEVBUF); 617 device_printf(sc->dev, "ERROR: cache sync command failed!\n"); 618 return 1; 619 } 620 621 device_printf(sc->dev, "clearing error table\n"); 622 if(ips_get_free_cmd(sc, ips_send_error_table_cmd, status, 623 IPS_NOWAIT_FLAG)){ 624 free(status, M_DEVBUF); 625 device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n"); 626 return 1; 627 } 628 if(COMMAND_ERROR(status)){ 629 device_printf(sc->dev, "ERROR: etable command failed!\n"); 630 free(status, M_DEVBUF); 631 return 1; 632 } 633 634 free(status, M_DEVBUF); 635 return 0; 636 } 637