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)){ 63 iobuf->bio_flags |=BIO_ERROR; 64 iobuf->bio_error = EIO; 65 printf("ips: io error, status= %d\n", command->status.value); 66 } 67 ips_insert_free_cmd(command->sc, command); 68 ipsd_finish(iobuf); 69 } 70 71 static void ips_io_request_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error) 72 { 73 ips_softc_t *sc; 74 ips_command_t *command = cmdptr; 75 ips_sg_element_t *sg_list; 76 ips_io_cmd *command_struct; 77 struct bio *iobuf = command->arg; 78 int i, length = 0; 79 u_int8_t cmdtype; 80 81 sc = command->sc; 82 if(error){ 83 printf("ips: error = %d in ips_sg_request_callback\n", error); 84 bus_dmamap_unload(command->data_dmatag, command->data_dmamap); 85 iobuf->bio_flags |= BIO_ERROR; 86 iobuf->bio_error = ENOMEM; 87 ips_insert_free_cmd(sc, command); 88 ipsd_finish(iobuf); 89 return; 90 } 91 command_struct = (ips_io_cmd *)command->command_buffer; 92 command_struct->id = command->id; 93 command_struct->drivenum = (uintptr_t)iobuf->bio_driver1; 94 if(segnum != 1){ 95 if(ips_read_request(iobuf)) 96 cmdtype = IPS_SG_READ_CMD; 97 else 98 cmdtype = IPS_SG_WRITE_CMD; 99 command_struct->segnum = segnum; 100 sg_list = (ips_sg_element_t *)((u_int8_t *) 101 command->command_buffer + IPS_COMMAND_LEN); 102 for(i = 0; i < segnum; i++){ 103 sg_list[i].addr = segments[i].ds_addr; 104 sg_list[i].len = segments[i].ds_len; 105 length += segments[i].ds_len; 106 } 107 command_struct->buffaddr = 108 (u_int32_t)command->command_phys_addr + IPS_COMMAND_LEN; 109 } else { 110 if(ips_read_request(iobuf)) 111 cmdtype = IPS_READ_CMD; 112 else 113 cmdtype = IPS_WRITE_CMD; 114 command_struct->buffaddr = segments[0].ds_addr; 115 length = segments[0].ds_len; 116 } 117 command_struct->command = cmdtype; 118 command_struct->lba = iobuf->bio_pblkno; 119 length = (length + IPS_BLKSIZE - 1)/IPS_BLKSIZE; 120 command_struct->length = length; 121 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 122 BUS_DMASYNC_PREWRITE); 123 if(ips_read_request(iobuf)) { 124 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 125 BUS_DMASYNC_PREREAD); 126 } else { 127 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 128 BUS_DMASYNC_PREWRITE); 129 } 130 PRINTF(10, "ips test: command id: %d segments: %d " 131 "pblkno: %lld length: %d, ds_len: %d\n", command->id, segnum, 132 iobuf->bio_pblkno, 133 length, segments[0].ds_len); 134 135 sc->ips_issue_cmd(command); 136 return; 137 } 138 139 static int ips_send_io_request(ips_command_t *command, struct bio *iobuf) 140 { 141 command->callback = ips_io_request_finish; 142 command->arg = iobuf; 143 PRINTF(10, "ips test: : bcount %ld\n", iobuf->bio_bcount); 144 bus_dmamap_load(command->data_dmatag, command->data_dmamap, 145 iobuf->bio_data, iobuf->bio_bcount, 146 ips_io_request_callback, command, 0); 147 return 0; 148 } 149 150 void ips_start_io_request(ips_softc_t *sc) 151 { 152 struct bio *iobuf; 153 ips_command_t *command; 154 155 iobuf = bioq_first(&sc->queue); 156 if(!iobuf) 157 return; 158 159 if (ips_get_free_cmd(sc, &command, 0)) 160 return; 161 162 bioq_remove(&sc->queue, iobuf); 163 ips_send_io_request(command, iobuf); 164 return; 165 } 166 167 /* Below are a series of functions for sending an adapter info request 168 * to the adapter. The flow order is: get, send, callback. It uses 169 * the generic finish callback at the top of this file. 170 * This can be used to get configuration/status info from the card */ 171 static void ips_adapter_info_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error) 172 { 173 ips_softc_t *sc; 174 ips_command_t *command = cmdptr; 175 ips_adapter_info_cmd *command_struct; 176 sc = command->sc; 177 if(error){ 178 ips_set_error(command, error); 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 if (sema_timedwait(&sc->cmd_sema, 30*hz) != 0) { 193 ips_set_error(command, ETIMEDOUT); 194 return; 195 } 196 197 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 198 BUS_DMASYNC_POSTREAD); 199 memcpy(&(sc->adapter_info), command->data_buffer, IPS_ADAPTER_INFO_LEN); 200 } 201 202 203 204 static int ips_send_adapter_info_cmd(ips_command_t *command) 205 { 206 int error = 0; 207 ips_softc_t *sc = command->sc; 208 209 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag, 210 /* alignemnt */ 1, 211 /* boundary */ 0, 212 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 213 /* highaddr */ BUS_SPACE_MAXADDR, 214 /* filter */ NULL, 215 /* filterarg */ NULL, 216 /* maxsize */ IPS_ADAPTER_INFO_LEN, 217 /* numsegs */ 1, 218 /* maxsegsize*/ IPS_ADAPTER_INFO_LEN, 219 /* flags */ 0, 220 /* lockfunc */ NULL, 221 /* lockarg */ NULL, 222 &command->data_dmatag) != 0) { 223 printf("ips: can't alloc dma tag for adapter status\n"); 224 error = ENOMEM; 225 goto exit; 226 } 227 if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 228 BUS_DMA_NOWAIT, &command->data_dmamap)){ 229 error = ENOMEM; 230 goto exit; 231 } 232 command->callback = ips_wakeup_callback; 233 error = bus_dmamap_load(command->data_dmatag, command->data_dmamap, 234 command->data_buffer,IPS_ADAPTER_INFO_LEN, 235 ips_adapter_info_callback, command, 236 BUS_DMA_NOWAIT); 237 238 if (error == 0) 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)){ 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 ips_drive_info_t *driveinfo; 276 277 sc = command->sc; 278 if(error){ 279 ips_set_error(command, error); 280 printf("ips: error = %d in ips_get_drive_info\n", error); 281 return; 282 } 283 command_struct = (ips_drive_cmd *)command->command_buffer; 284 command_struct->command = IPS_DRIVE_INFO_CMD; 285 command_struct->id = command->id; 286 command_struct->buffaddr = segments[0].ds_addr; 287 288 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 289 BUS_DMASYNC_PREWRITE); 290 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 291 BUS_DMASYNC_PREREAD); 292 sc->ips_issue_cmd(command); 293 if (sema_timedwait(&sc->cmd_sema, 10*hz) != 0) { 294 ips_set_error(command, ETIMEDOUT); 295 return; 296 } 297 298 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 299 BUS_DMASYNC_POSTREAD); 300 driveinfo = command->data_buffer; 301 memcpy(sc->drives, driveinfo->drives, sizeof(ips_drive_t) * 8); 302 sc->drivecount = driveinfo->drivecount; 303 device_printf(sc->dev, "logical drives: %d\n",sc->drivecount); 304 } 305 306 static int ips_send_drive_info_cmd(ips_command_t *command) 307 { 308 int error = 0; 309 ips_softc_t *sc = command->sc; 310 311 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag, 312 /* alignemnt */ 1, 313 /* boundary */ 0, 314 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 315 /* highaddr */ BUS_SPACE_MAXADDR, 316 /* filter */ NULL, 317 /* filterarg */ NULL, 318 /* maxsize */ IPS_DRIVE_INFO_LEN, 319 /* numsegs */ 1, 320 /* maxsegsize*/ IPS_DRIVE_INFO_LEN, 321 /* flags */ 0, 322 /* lockfunc */ NULL, 323 /* lockarg */ NULL, 324 &command->data_dmatag) != 0) { 325 printf("ips: can't alloc dma tag for drive status\n"); 326 error = ENOMEM; 327 goto exit; 328 } 329 if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 330 BUS_DMA_NOWAIT, &command->data_dmamap)){ 331 error = ENOMEM; 332 goto exit; 333 } 334 command->callback = ips_wakeup_callback; 335 error = bus_dmamap_load(command->data_dmatag, command->data_dmamap, 336 command->data_buffer,IPS_DRIVE_INFO_LEN, 337 ips_drive_info_callback, command, 338 BUS_DMA_NOWAIT); 339 if (error == 0) 340 bus_dmamap_unload(command->data_dmatag, command->data_dmamap); 341 342 exit: 343 /* I suppose I should clean up my memory allocations */ 344 bus_dmamem_free(command->data_dmatag, command->data_buffer, 345 command->data_dmamap); 346 bus_dma_tag_destroy(command->data_dmatag); 347 ips_insert_free_cmd(sc, command); 348 return error; 349 350 } 351 int ips_get_drive_info(ips_softc_t *sc) 352 { 353 int error = 0; 354 ips_command_t *command; 355 356 if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG) > 0){ 357 device_printf(sc->dev, "unable to get drive configuration\n"); 358 return ENXIO; 359 } 360 ips_send_drive_info_cmd(command); 361 if(COMMAND_ERROR(command)){ 362 error = ENXIO; 363 } 364 return error; 365 } 366 367 /* Below is a pair of functions for making sure data is safely 368 * on disk by flushing the adapter's cache. */ 369 static int ips_send_flush_cache_cmd(ips_command_t *command) 370 { 371 ips_softc_t *sc = command->sc; 372 ips_generic_cmd *command_struct; 373 374 PRINTF(10,"ips test: got a command, building flush command\n"); 375 command->callback = ips_wakeup_callback; 376 command_struct = (ips_generic_cmd *)command->command_buffer; 377 command_struct->command = IPS_CACHE_FLUSH_CMD; 378 command_struct->id = command->id; 379 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 380 BUS_DMASYNC_PREWRITE); 381 sc->ips_issue_cmd(command); 382 if (COMMAND_ERROR(command) == 0) 383 sema_wait(&sc->cmd_sema); 384 ips_insert_free_cmd(sc, command); 385 return 0; 386 } 387 388 int ips_flush_cache(ips_softc_t *sc) 389 { 390 ips_command_t *command; 391 392 device_printf(sc->dev, "flushing cache\n"); 393 if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){ 394 device_printf(sc->dev, "ERROR: unable to get a command! can't flush cache!\n"); 395 } 396 ips_send_flush_cache_cmd(command); 397 if(COMMAND_ERROR(command)){ 398 device_printf(sc->dev, "ERROR: cache flush command failed!\n"); 399 } 400 return 0; 401 } 402 403 /* Simplified localtime to provide timevalues for ffdc. 404 * Taken from libc/stdtime/localtime.c 405 */ 406 void static ips_ffdc_settime(ips_adapter_ffdc_cmd *command, time_t sctime) 407 { 408 long days, rem, y; 409 int yleap, *ip, month; 410 int year_lengths[2] = { IPS_DAYSPERNYEAR, IPS_DAYSPERLYEAR }; 411 int mon_lengths[2][IPS_MONSPERYEAR] = { 412 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, 413 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } 414 }; 415 416 days = sctime / IPS_SECSPERDAY; 417 rem = sctime % IPS_SECSPERDAY; 418 419 command->hour = rem / IPS_SECSPERHOUR; 420 rem = rem % IPS_SECSPERHOUR; 421 422 command->minute = rem / IPS_SECSPERMIN; 423 command->second = rem % IPS_SECSPERMIN; 424 425 y = IPS_EPOCH_YEAR; 426 while (days < 0 || days >= (long) year_lengths[yleap = ips_isleap(y)]) { 427 long newy; 428 429 newy = y + days / IPS_DAYSPERNYEAR; 430 if (days < 0) 431 --newy; 432 days -= (newy - y) * IPS_DAYSPERNYEAR + 433 IPS_LEAPS_THRU_END_OF(newy - 1) - 434 IPS_LEAPS_THRU_END_OF(y - 1); 435 y = newy; 436 } 437 command->yearH = y / 100; 438 command->yearL = y % 100; 439 ip = mon_lengths[yleap]; 440 for(month = 0; days >= (long) ip[month]; ++month) 441 days = days - (long) ip[month]; 442 command->month = month + 1; 443 command->day = days + 1; 444 } 445 446 static int ips_send_ffdc_reset_cmd(ips_command_t *command) 447 { 448 ips_softc_t *sc = command->sc; 449 ips_adapter_ffdc_cmd *command_struct; 450 451 PRINTF(10,"ips test: got a command, building ffdc reset command\n"); 452 command->callback = ips_wakeup_callback; 453 command_struct = (ips_adapter_ffdc_cmd *)command->command_buffer; 454 command_struct->command = IPS_FFDC_CMD; 455 command_struct->id = command->id; 456 command_struct->reset_count = sc->ffdc_resetcount; 457 command_struct->reset_type = 0x0; 458 ips_ffdc_settime(command_struct, sc->ffdc_resettime.tv_sec); 459 460 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 461 BUS_DMASYNC_PREWRITE); 462 sc->ips_issue_cmd(command); 463 if (COMMAND_ERROR(command) == 0) 464 sema_wait(&sc->cmd_sema); 465 ips_insert_free_cmd(sc, command); 466 return 0; 467 } 468 469 int ips_ffdc_reset(ips_softc_t *sc) 470 { 471 ips_command_t *command; 472 473 if (ips_get_free_cmd(sc, &command, IPS_STATIC_FLAG)){ 474 device_printf(sc->dev, "ERROR: unable to get a command! can't send ffdc reset!\n"); 475 } 476 ips_send_ffdc_reset_cmd(command); 477 if(COMMAND_ERROR(command)){ 478 device_printf(sc->dev, "ERROR: ffdc reset command failed!\n"); 479 } 480 return 0; 481 } 482 483 static void ips_write_nvram(ips_command_t *command){ 484 ips_softc_t *sc = command->sc; 485 ips_rw_nvram_cmd *command_struct; 486 ips_nvram_page5 *nvram; 487 488 /*FIXME check for error */ 489 command->callback = ips_wakeup_callback; 490 command_struct = (ips_rw_nvram_cmd *)command->command_buffer; 491 command_struct->command = IPS_RW_NVRAM_CMD; 492 command_struct->id = command->id; 493 command_struct->pagenum = 5; 494 command_struct->rw = 1; /*write*/ 495 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 496 BUS_DMASYNC_POSTREAD); 497 nvram = command->data_buffer; 498 /* retrieve adapter info and save in sc */ 499 sc->adapter_type = nvram->adapter_type; 500 501 strncpy(nvram->driver_high, IPS_VERSION_MAJOR, 4); 502 strncpy(nvram->driver_low, IPS_VERSION_MINOR, 4); 503 nvram->operating_system = IPS_OS_FREEBSD; 504 bus_dmamap_sync(sc->command_dmatag, command->command_dmamap, 505 BUS_DMASYNC_PREWRITE); 506 sc->ips_issue_cmd(command); 507 } 508 509 static void ips_read_nvram_callback(void *cmdptr, bus_dma_segment_t *segments,int segnum, int error) 510 { 511 ips_softc_t *sc; 512 ips_command_t *command = cmdptr; 513 ips_rw_nvram_cmd *command_struct; 514 sc = command->sc; 515 if(error){ 516 ips_set_error(command, error); 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 if (sema_timedwait(&sc->cmd_sema, 30*hz) != 0) { 533 ips_set_error(command, ETIMEDOUT); 534 return; 535 } 536 bus_dmamap_sync(command->data_dmatag, command->data_dmamap, 537 BUS_DMASYNC_POSTWRITE); 538 } 539 540 static int ips_read_nvram(ips_command_t *command) 541 { 542 int error = 0; 543 ips_softc_t *sc = command->sc; 544 545 if (bus_dma_tag_create( /* parent */ sc->adapter_dmatag, 546 /* alignemnt */ 1, 547 /* boundary */ 0, 548 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 549 /* highaddr */ BUS_SPACE_MAXADDR, 550 /* filter */ NULL, 551 /* filterarg */ NULL, 552 /* maxsize */ IPS_NVRAM_PAGE_SIZE, 553 /* numsegs */ 1, 554 /* maxsegsize*/ IPS_NVRAM_PAGE_SIZE, 555 /* flags */ 0, 556 /* lockfunc */ NULL, 557 /* lockarg */ NULL, 558 &command->data_dmatag) != 0) { 559 printf("ips: can't alloc dma tag for nvram\n"); 560 error = ENOMEM; 561 goto exit; 562 } 563 if(bus_dmamem_alloc(command->data_dmatag, &command->data_buffer, 564 BUS_DMA_NOWAIT, &command->data_dmamap)){ 565 error = ENOMEM; 566 goto exit; 567 } 568 command->callback = ips_write_nvram; 569 error = bus_dmamap_load(command->data_dmatag, command->data_dmamap, 570 command->data_buffer,IPS_NVRAM_PAGE_SIZE, 571 ips_read_nvram_callback, command, 572 BUS_DMA_NOWAIT); 573 if (error == 0) 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)){ 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_ERROR(command) == 0) 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_ERROR(command) == 0) 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)){ 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)){ 665 device_printf(sc->dev, "ERROR: etable command failed!\n"); 666 return 1; 667 } 668 669 return 0; 670 } 671