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