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