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