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 = (uintptr_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 /* lockfunc */ busdma_lock_mutex, 228 /* lockarg */ &Giant, 229 &command->data_dmatag) != 0) { 230 printf("ips: can't alloc dma tag for adapter status\n"); 231 error = ENOMEM; 232 goto exit; 233 } 234 if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 235 BUS_DMA_NOWAIT, &command->data_dmamap)){ 236 error = ENOMEM; 237 goto exit; 238 } 239 command->callback = ips_wakeup_callback; 240 mtx_lock(&sc->cmd_mtx); 241 bus_dmamap_load(command->data_dmatag, command->data_dmamap, 242 command->data_buffer,IPS_ADAPTER_INFO_LEN, 243 ips_adapter_info_callback, command, BUS_DMA_NOWAIT); 244 245 if ((status->value == IPS_ERROR_STATUS) || 246 (msleep(status, &sc->cmd_mtx, 0, "ips", 30*hz) == EWOULDBLOCK)) 247 error = ETIMEDOUT; 248 mtx_unlock(&sc->cmd_mtx); 249 250 if (error == 0) { 251 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 252 BUS_DMASYNC_POSTREAD); 253 memcpy(&(sc->adapter_info), command->data_buffer, 254 IPS_ADAPTER_INFO_LEN); 255 } 256 bus_dmamap_unload(command->data_dmatag, command->data_dmamap); 257 258 exit: 259 /* I suppose I should clean up my memory allocations */ 260 bus_dmamem_free(command->data_dmatag, command->data_buffer, 261 command->data_dmamap); 262 bus_dma_tag_destroy(command->data_dmatag); 263 ips_insert_free_cmd(sc, command); 264 return error; 265 } 266 267 int ips_get_adapter_info(ips_softc_t *sc) 268 { 269 int error = 0; 270 ips_cmd_status_t *status; 271 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT|M_ZERO); 272 if(!status) 273 return ENOMEM; 274 if(ips_get_free_cmd(sc, ips_send_adapter_info_cmd, status, 275 IPS_NOWAIT_FLAG) > 0){ 276 device_printf(sc->dev, "unable to get adapter configuration\n"); 277 free(status, M_DEVBUF); 278 return ENXIO; 279 } 280 if (COMMAND_ERROR(status)){ 281 error = ENXIO; 282 } 283 free(status, M_DEVBUF); 284 return error; 285 } 286 287 /* Below are a series of functions for sending a drive info request 288 * to the adapter. The flow order is: get, send, callback. It uses 289 * the generic finish callback at the top of this file. 290 * This can be used to get drive status info from the card */ 291 static void ips_drive_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error) 292 { 293 ips_softc_t *sc; 294 ips_command_t *command = cmdptr; 295 ips_drive_cmd *command_struct; 296 sc = command->sc; 297 if(error){ 298 ips_cmd_status_t * status = command->arg; 299 status->value = IPS_ERROR_STATUS; 300 ips_insert_free_cmd(sc, command); 301 printf("ips: error = %d in ips_get_drive_info\n", error); 302 return; 303 } 304 command_struct = (ips_drive_cmd *)command->command_buffer; 305 command_struct->command = IPS_DRIVE_INFO_CMD; 306 command_struct->id = command->id; 307 command_struct->buffaddr = segments[0].ds_addr; 308 309 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 310 BUS_DMASYNC_PREWRITE); 311 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 312 BUS_DMASYNC_PREREAD); 313 sc->ips_issue_cmd(command); 314 } 315 316 static int ips_send_drive_info_cmd(ips_command_t *command) 317 { 318 int error = 0; 319 ips_softc_t *sc = command->sc; 320 ips_cmd_status_t *status = command->arg; 321 ips_drive_info_t *driveinfo; 322 323 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag, 324 /* alignemnt */ 1, 325 /* boundary */ 0, 326 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 327 /* highaddr */ BUS_SPACE_MAXADDR, 328 /* filter */ NULL, 329 /* filterarg */ NULL, 330 /* maxsize */ IPS_DRIVE_INFO_LEN, 331 /* numsegs */ 1, 332 /* maxsegsize*/ IPS_DRIVE_INFO_LEN, 333 /* flags */ 0, 334 /* lockfunc */ busdma_lock_mutex, 335 /* lockarg */ &Giant, 336 &command->data_dmatag) != 0) { 337 printf("ips: can't alloc dma tag for drive status\n"); 338 error = ENOMEM; 339 goto exit; 340 } 341 if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 342 BUS_DMA_NOWAIT, &command->data_dmamap)){ 343 error = ENOMEM; 344 goto exit; 345 } 346 command->callback = ips_wakeup_callback; 347 mtx_lock(&sc->cmd_mtx); 348 bus_dmamap_load(command->data_dmatag, command->data_dmamap, 349 command->data_buffer,IPS_DRIVE_INFO_LEN, 350 ips_drive_info_callback, command, BUS_DMA_NOWAIT); 351 if ((status->value == IPS_ERROR_STATUS) || 352 (msleep(status, &sc->cmd_mtx, 0, "ips", 10*hz) == EWOULDBLOCK)) 353 error = ETIMEDOUT; 354 mtx_unlock(&sc->cmd_mtx); 355 356 if (error == 0) { 357 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 358 BUS_DMASYNC_POSTREAD); 359 driveinfo = command->data_buffer; 360 memcpy(sc->drives, driveinfo->drives, sizeof(ips_drive_t) * 8); 361 sc->drivecount = driveinfo->drivecount; 362 device_printf(sc->dev, "logical drives: %d\n",sc->drivecount); 363 } 364 bus_dmamap_unload(command->data_dmatag, command->data_dmamap); 365 366 exit: 367 /* I suppose I should clean up my memory allocations */ 368 bus_dmamem_free(command->data_dmatag, command->data_buffer, 369 command->data_dmamap); 370 bus_dma_tag_destroy(command->data_dmatag); 371 ips_insert_free_cmd(sc, command); 372 return error; 373 374 } 375 int ips_get_drive_info(ips_softc_t *sc) 376 { 377 int error = 0; 378 ips_cmd_status_t *status; 379 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT|M_ZERO); 380 if(!status) 381 return ENOMEM; 382 if(ips_get_free_cmd(sc, ips_send_drive_info_cmd, status, 383 IPS_NOWAIT_FLAG) > 0){ 384 free(status, M_DEVBUF); 385 device_printf(sc->dev, "unable to get drive configuration\n"); 386 return ENXIO; 387 } 388 if(COMMAND_ERROR(status)){ 389 error = ENXIO; 390 } 391 free(status, M_DEVBUF); 392 return error; 393 } 394 395 /* Below is a pair of functions for making sure data is safely 396 * on disk by flushing the adapter's cache. */ 397 static int ips_send_flush_cache_cmd(ips_command_t *command) 398 { 399 ips_softc_t *sc = command->sc; 400 ips_cmd_status_t *status = command->arg; 401 ips_generic_cmd *command_struct; 402 403 PRINTF(10,"ips test: got a command, building flush command\n"); 404 command->callback = ips_wakeup_callback; 405 command_struct = (ips_generic_cmd *)command->command_buffer; 406 command_struct->command = IPS_CACHE_FLUSH_CMD; 407 command_struct->id = command->id; 408 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 409 BUS_DMASYNC_PREWRITE); 410 mtx_lock(&sc->cmd_mtx); 411 sc->ips_issue_cmd(command); 412 if (status->value != IPS_ERROR_STATUS) 413 msleep(status, &sc->cmd_mtx, 0, "flush2", 0); 414 mtx_unlock(&sc->cmd_mtx); 415 ips_insert_free_cmd(sc, command); 416 return 0; 417 } 418 419 int ips_flush_cache(ips_softc_t *sc) 420 { 421 ips_cmd_status_t *status; 422 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT|M_ZERO); 423 if(!status) 424 return ENOMEM; 425 device_printf(sc->dev, "flushing cache\n"); 426 if(ips_get_free_cmd(sc, ips_send_flush_cache_cmd, status, 427 IPS_NOWAIT_FLAG)){ 428 free(status, M_DEVBUF); 429 device_printf(sc->dev, "ERROR: unable to get a command! can't flush cache!\n"); 430 } 431 if(COMMAND_ERROR(status)){ 432 device_printf(sc->dev, "ERROR: cache flush command failed!\n"); 433 } 434 free(status, M_DEVBUF); 435 return 0; 436 } 437 438 static void ips_write_nvram(ips_command_t *command){ 439 ips_softc_t *sc = command->sc; 440 ips_rw_nvram_cmd *command_struct; 441 ips_nvram_page5 *nvram; 442 443 /*FIXME check for error */ 444 command->callback = ips_wakeup_callback; 445 command_struct = (ips_rw_nvram_cmd *)command->command_buffer; 446 command_struct->command = IPS_RW_NVRAM_CMD; 447 command_struct->id = command->id; 448 command_struct->pagenum = 5; 449 command_struct->rw = 1; /*write*/ 450 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 451 BUS_DMASYNC_POSTREAD); 452 nvram = command->data_buffer; 453 strncpy(nvram->driver_high, IPS_VERSION_MAJOR, 4); 454 strncpy(nvram->driver_low, IPS_VERSION_MINOR, 4); 455 nvram->operating_system = IPS_OS_FREEBSD; 456 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 457 BUS_DMASYNC_PREWRITE); 458 sc->ips_issue_cmd(command); 459 } 460 461 static void ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error) 462 { 463 ips_softc_t *sc; 464 ips_command_t *command = cmdptr; 465 ips_rw_nvram_cmd *command_struct; 466 sc = command->sc; 467 if(error){ 468 ips_cmd_status_t * status = command->arg; 469 status->value = IPS_ERROR_STATUS; 470 ips_insert_free_cmd(sc, command); 471 printf("ips: error = %d in ips_read_nvram_callback\n", error); 472 return; 473 } 474 command_struct = (ips_rw_nvram_cmd *)command->command_buffer; 475 command_struct->command = IPS_RW_NVRAM_CMD; 476 command_struct->id = command->id; 477 command_struct->pagenum = 5; 478 command_struct->rw = 0; 479 command_struct->buffaddr = segments[0].ds_addr; 480 481 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 482 BUS_DMASYNC_PREWRITE); 483 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 484 BUS_DMASYNC_PREREAD); 485 sc->ips_issue_cmd(command); 486 } 487 488 static int ips_read_nvram(ips_command_t *command){ 489 int error = 0; 490 ips_softc_t *sc = command->sc; 491 ips_cmd_status_t *status = command->arg; 492 493 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag, 494 /* alignemnt */ 1, 495 /* boundary */ 0, 496 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 497 /* highaddr */ BUS_SPACE_MAXADDR, 498 /* filter */ NULL, 499 /* filterarg */ NULL, 500 /* maxsize */ IPS_NVRAM_PAGE_SIZE, 501 /* numsegs */ 1, 502 /* maxsegsize*/ IPS_NVRAM_PAGE_SIZE, 503 /* flags */ 0, 504 /* lockfunc */ busdma_lock_mutex, 505 /* lockarg */ &Giant, 506 &command->data_dmatag) != 0) { 507 printf("ips: can't alloc dma tag for nvram\n"); 508 error = ENOMEM; 509 goto exit; 510 } 511 if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 512 BUS_DMA_NOWAIT, &command->data_dmamap)){ 513 error = ENOMEM; 514 goto exit; 515 } 516 command->callback = ips_write_nvram; 517 mtx_lock(&sc->cmd_mtx); 518 bus_dmamap_load(command->data_dmatag, command->data_dmamap, 519 command->data_buffer,IPS_NVRAM_PAGE_SIZE, 520 ips_read_nvram_callback, command, BUS_DMA_NOWAIT); 521 if ((status->value == IPS_ERROR_STATUS) || 522 (msleep(status, &sc->cmd_mtx, 0, "ips", 0) == EWOULDBLOCK)) 523 error = ETIMEDOUT; 524 mtx_unlock(&sc->cmd_mtx); 525 526 if (error == 0) { 527 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 528 BUS_DMASYNC_POSTWRITE); 529 } 530 bus_dmamap_unload(command->data_dmatag, command->data_dmamap); 531 532 exit: 533 bus_dmamem_free(command->data_dmatag, command->data_buffer, 534 command->data_dmamap); 535 bus_dma_tag_destroy(command->data_dmatag); 536 ips_insert_free_cmd(sc, command); 537 return error; 538 } 539 540 int ips_update_nvram(ips_softc_t *sc) 541 { 542 ips_cmd_status_t *status; 543 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT|M_ZERO); 544 if(!status) 545 return ENOMEM; 546 if(ips_get_free_cmd(sc, ips_read_nvram, status, IPS_NOWAIT_FLAG)){ 547 free(status, M_DEVBUF); 548 device_printf(sc->dev, "ERROR: unable to get a command! can't update nvram\n"); 549 return 1; 550 } 551 if(COMMAND_ERROR(status)){ 552 device_printf(sc->dev, "ERROR: nvram update command failed!\n"); 553 } 554 free(status, M_DEVBUF); 555 return 0; 556 557 558 } 559 560 561 static int ips_send_config_sync_cmd(ips_command_t *command) 562 { 563 ips_softc_t *sc = command->sc; 564 ips_cmd_status_t *status = command->arg; 565 ips_generic_cmd *command_struct; 566 567 PRINTF(10,"ips test: got a command, building flush command\n"); 568 command->callback = ips_wakeup_callback; 569 command_struct = (ips_generic_cmd *)command->command_buffer; 570 command_struct->command = IPS_CONFIG_SYNC_CMD; 571 command_struct->id = command->id; 572 command_struct->reserve2 = IPS_POCL; 573 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 574 BUS_DMASYNC_PREWRITE); 575 mtx_lock(&sc->cmd_mtx); 576 sc->ips_issue_cmd(command); 577 if (status->value != IPS_ERROR_STATUS) 578 msleep(status, &sc->cmd_mtx, 0, "ipssyn", 0); 579 mtx_unlock(&sc->cmd_mtx); 580 ips_insert_free_cmd(sc, command); 581 return 0; 582 } 583 584 static int ips_send_error_table_cmd(ips_command_t *command) 585 { 586 ips_softc_t *sc = command->sc; 587 ips_cmd_status_t *status = command->arg; 588 ips_generic_cmd *command_struct; 589 590 PRINTF(10,"ips test: got a command, building errortable command\n"); 591 command->callback = ips_wakeup_callback; 592 command_struct = (ips_generic_cmd *)command->command_buffer; 593 command_struct->command = IPS_ERROR_TABLE_CMD; 594 command_struct->id = command->id; 595 command_struct->reserve2 = IPS_CSL; 596 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 597 BUS_DMASYNC_PREWRITE); 598 mtx_lock(&sc->cmd_mtx); 599 sc->ips_issue_cmd(command); 600 if (status->value != IPS_ERROR_STATUS) 601 msleep(status, &sc->cmd_mtx, 0, "ipsetc", 0); 602 mtx_unlock(&sc->cmd_mtx); 603 ips_insert_free_cmd(sc, command); 604 return 0; 605 } 606 607 608 int ips_clear_adapter(ips_softc_t *sc) 609 { 610 ips_cmd_status_t *status; 611 status = malloc(sizeof(ips_cmd_status_t), M_DEVBUF, M_NOWAIT|M_ZERO); 612 if(!status) 613 return ENOMEM; 614 device_printf(sc->dev, "syncing config\n"); 615 if(ips_get_free_cmd(sc, ips_send_config_sync_cmd, status, 616 IPS_NOWAIT_FLAG)){ 617 free(status, M_DEVBUF); 618 device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n"); 619 return 1; 620 } 621 if(COMMAND_ERROR(status)){ 622 free(status, M_DEVBUF); 623 device_printf(sc->dev, "ERROR: cache sync command failed!\n"); 624 return 1; 625 } 626 627 device_printf(sc->dev, "clearing error table\n"); 628 if(ips_get_free_cmd(sc, ips_send_error_table_cmd, status, 629 IPS_NOWAIT_FLAG)){ 630 free(status, M_DEVBUF); 631 device_printf(sc->dev, "ERROR: unable to get a command! can't sync cache!\n"); 632 return 1; 633 } 634 if(COMMAND_ERROR(status)){ 635 device_printf(sc->dev, "ERROR: etable command failed!\n"); 636 free(status, M_DEVBUF); 637 return 1; 638 } 639 640 free(status, M_DEVBUF); 641 return 0; 642 } 643