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