twe.c (111119) | twe.c (118508) |
---|---|
1/*- 2 * Copyright (c) 2000 Michael Smith 3 * Copyright (c) 2000 BSDi 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: --- 10 unchanged lines hidden (view full) --- 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 * | 1/*- 2 * Copyright (c) 2000 Michael Smith 3 * Copyright (c) 2000 BSDi 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: --- 10 unchanged lines hidden (view full) --- 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: head/sys/dev/twe/twe.c 111119 2003-02-19 05:47:46Z imp $ | 27 * $FreeBSD: head/sys/dev/twe/twe.c 118508 2003-08-05 19:55:21Z ps $ |
28 */ 29 30/* 31 * Driver for the 3ware Escalade family of IDE RAID controllers. 32 */ 33 34#include <dev/twe/twe_compat.h> 35#include <dev/twe/twereg.h> --- 19 unchanged lines hidden (view full) --- 55#endif 56static int twe_set_param(struct twe_softc *sc, int table_id, int param_id, int param_size, 57 void *data); 58static int twe_init_connection(struct twe_softc *sc, int mode); 59static int twe_wait_request(struct twe_request *tr); 60static int twe_immediate_request(struct twe_request *tr); 61static void twe_completeio(struct twe_request *tr); 62static void twe_reset(struct twe_softc *sc); | 28 */ 29 30/* 31 * Driver for the 3ware Escalade family of IDE RAID controllers. 32 */ 33 34#include <dev/twe/twe_compat.h> 35#include <dev/twe/twereg.h> --- 19 unchanged lines hidden (view full) --- 55#endif 56static int twe_set_param(struct twe_softc *sc, int table_id, int param_id, int param_size, 57 void *data); 58static int twe_init_connection(struct twe_softc *sc, int mode); 59static int twe_wait_request(struct twe_request *tr); 60static int twe_immediate_request(struct twe_request *tr); 61static void twe_completeio(struct twe_request *tr); 62static void twe_reset(struct twe_softc *sc); |
63static void twe_add_unit(struct twe_softc *sc, int unit); 64static void twe_del_unit(struct twe_softc *sc, int unit); |
|
63 64/* 65 * Command I/O to controller. 66 */ 67static int twe_start(struct twe_request *tr); 68static void twe_done(struct twe_softc *sc); 69static void twe_complete(struct twe_softc *sc); 70static int twe_wait_status(struct twe_softc *sc, u_int32_t status, int timeout); --- 113 unchanged lines hidden (view full) --- 184 if (i >= TWE_MAX_RESET_TRIES) { 185 twe_printf(sc, "can't initialise controller, giving up\n"); 186 return(ENXIO); 187 } 188 189 return(0); 190} 191 | 65 66/* 67 * Command I/O to controller. 68 */ 69static int twe_start(struct twe_request *tr); 70static void twe_done(struct twe_softc *sc); 71static void twe_complete(struct twe_softc *sc); 72static int twe_wait_status(struct twe_softc *sc, u_int32_t status, int timeout); --- 113 unchanged lines hidden (view full) --- 186 if (i >= TWE_MAX_RESET_TRIES) { 187 twe_printf(sc, "can't initialise controller, giving up\n"); 188 return(ENXIO); 189 } 190 191 return(0); 192} 193 |
192/******************************************************************************** 193 * Locate disk devices and attach children to them. 194 */ 195void 196twe_init(struct twe_softc *sc) | 194static void 195twe_add_unit(struct twe_softc *sc, int unit) |
197{ 198 struct twe_drive *dr; | 196{ 197 struct twe_drive *dr; |
199 int i, table; | 198 int table; |
200 u_int16_t dsize; | 199 u_int16_t dsize; |
201 TWE_Param *drives, *param; | 200 TWE_Param *drives = NULL, *param = NULL; |
202 TWE_Unit_Descriptor *ud; 203 | 201 TWE_Unit_Descriptor *ud; 202 |
203 if (unit < 0 || unit > TWE_MAX_UNITS) 204 return; |
|
204 205 /* 206 * The controller is in a safe state, so try to find drives attached to it. 207 */ 208 if ((drives = twe_get_param(sc, TWE_PARAM_UNITSUMMARY, TWE_PARAM_UNITSUMMARY_Status, 209 TWE_MAX_UNITS, NULL)) == NULL) { 210 twe_printf(sc, "can't detect attached units\n"); 211 return; 212 } | 205 206 /* 207 * The controller is in a safe state, so try to find drives attached to it. 208 */ 209 if ((drives = twe_get_param(sc, TWE_PARAM_UNITSUMMARY, TWE_PARAM_UNITSUMMARY_Status, 210 TWE_MAX_UNITS, NULL)) == NULL) { 211 twe_printf(sc, "can't detect attached units\n"); 212 return; 213 } |
213 214 /* 215 * For each detected unit, create a child device. 216 */ 217 for (i = 0, dr = &sc->twe_drive[0]; i < TWE_MAX_UNITS; i++, dr++) { | |
218 | 214 |
219 /* check that the drive is online */ 220 if (!(drives->data[i] & TWE_PARAM_UNITSTATUS_Online)) 221 continue; | 215 dr = &sc->twe_drive[unit]; 216 /* check that the drive is online */ 217 if (!(drives->data[unit] & TWE_PARAM_UNITSTATUS_Online)) 218 goto out; |
222 | 219 |
223 table = TWE_PARAM_UNITINFO + i; | 220 table = TWE_PARAM_UNITINFO + unit; |
224 | 221 |
225 if (twe_get_param_4(sc, table, TWE_PARAM_UNITINFO_Capacity, &dr->td_size)) { 226 twe_printf(sc, "error fetching capacity for unit %d\n", i); 227 continue; 228 } 229 if (twe_get_param_1(sc, table, TWE_PARAM_UNITINFO_Status, &dr->td_state)) { 230 twe_printf(sc, "error fetching state for unit %d\n", i); 231 continue; 232 } 233 if (twe_get_param_2(sc, table, TWE_PARAM_UNITINFO_DescriptorSize, &dsize)) { 234 twe_printf(sc, "error fetching descriptor size for unit %d\n", i); 235 continue; 236 } 237 if ((param = twe_get_param(sc, table, TWE_PARAM_UNITINFO_Descriptor, dsize - 3, NULL)) == NULL) { 238 twe_printf(sc, "error fetching descriptor for unit %d\n", i); 239 continue; 240 } 241 ud = (TWE_Unit_Descriptor *)param->data; 242 dr->td_type = ud->configuration; | 222 if (twe_get_param_4(sc, table, TWE_PARAM_UNITINFO_Capacity, &dr->td_size)) { 223 twe_printf(sc, "error fetching capacity for unit %d\n", unit); 224 goto out; 225 } 226 if (twe_get_param_1(sc, table, TWE_PARAM_UNITINFO_Status, &dr->td_state)) { 227 twe_printf(sc, "error fetching state for unit %d\n", unit); 228 goto out; 229 } 230 if (twe_get_param_2(sc, table, TWE_PARAM_UNITINFO_DescriptorSize, &dsize)) { 231 twe_printf(sc, "error fetching descriptor size for unit %d\n", unit); 232 goto out; 233 } 234 if ((param = twe_get_param(sc, table, TWE_PARAM_UNITINFO_Descriptor, dsize - 3, NULL)) == NULL) { 235 twe_printf(sc, "error fetching descriptor for unit %d\n", unit); 236 goto out; 237 } 238 ud = (TWE_Unit_Descriptor *)param->data; 239 dr->td_type = ud->configuration; 240 241 /* build synthetic geometry as per controller internal rules */ 242 if (dr->td_size > 0x200000) { 243 dr->td_heads = 255; 244 dr->td_sectors = 63; 245 } else { 246 dr->td_heads = 64; 247 dr->td_sectors = 32; 248 } 249 dr->td_cylinders = dr->td_size / (dr->td_heads * dr->td_sectors); 250 dr->td_unit = unit; 251 252 twe_attach_drive(sc, dr); 253 254out: 255 if (param != NULL) |
243 free(param, M_DEVBUF); | 256 free(param, M_DEVBUF); |
257 if (drives != NULL) 258 free(drives, M_DEVBUF); 259} |
|
244 | 260 |
245 /* build synthetic geometry as per controller internal rules */ 246 if (dr->td_size > 0x200000) { 247 dr->td_heads = 255; 248 dr->td_sectors = 63; 249 } else { 250 dr->td_heads = 64; 251 dr->td_sectors = 32; 252 } 253 dr->td_cylinders = dr->td_size / (dr->td_heads * dr->td_sectors); 254 dr->td_unit = i; | 261static void 262twe_del_unit(struct twe_softc *sc, int unit) 263{ |
255 | 264 |
256 twe_attach_drive(sc, dr); 257 } 258 free(drives, M_DEVBUF); | 265 if (unit < 0 || unit > TWE_MAX_UNITS) 266 return; |
259 | 267 |
268 twe_detach_drive(sc, unit); 269} 270 271/******************************************************************************** 272 * Locate disk devices and attach children to them. 273 */ 274void 275twe_init(struct twe_softc *sc) 276{ 277 int i; 278 |
|
260 /* | 279 /* |
280 * Scan for drives 281 */ 282 for (i = 0; i < TWE_MAX_UNITS; i++) 283 twe_add_unit(sc, i); 284 285 /* |
|
261 * Initialise connection with controller. 262 */ 263 twe_init_connection(sc, TWE_INIT_MESSAGE_CREDITS); 264 265#ifdef TWE_SHUTDOWN_NOTIFICATION 266 /* 267 * Tell the controller we support shutdown notification. 268 */ --- 173 unchanged lines hidden (view full) --- 442/******************************************************************************** 443 * Handle controller-specific control operations. 444 */ 445int 446twe_ioctl(struct twe_softc *sc, int cmd, void *addr) 447{ 448 struct twe_usercommand *tu = (struct twe_usercommand *)addr; 449 struct twe_paramcommand *tp = (struct twe_paramcommand *)addr; | 286 * Initialise connection with controller. 287 */ 288 twe_init_connection(sc, TWE_INIT_MESSAGE_CREDITS); 289 290#ifdef TWE_SHUTDOWN_NOTIFICATION 291 /* 292 * Tell the controller we support shutdown notification. 293 */ --- 173 unchanged lines hidden (view full) --- 467/******************************************************************************** 468 * Handle controller-specific control operations. 469 */ 470int 471twe_ioctl(struct twe_softc *sc, int cmd, void *addr) 472{ 473 struct twe_usercommand *tu = (struct twe_usercommand *)addr; 474 struct twe_paramcommand *tp = (struct twe_paramcommand *)addr; |
475 struct twe_drivecommand *td = (struct twe_drivecommand *)addr; |
|
450 union twe_statrequest *ts = (union twe_statrequest *)addr; 451 TWE_Param *param; 452 void *data; 453 int *arg = (int *)addr; 454 struct twe_request *tr; 455 u_int8_t srid; 456 int s, error; 457 458 error = 0; 459 switch(cmd) { 460 /* handle a command from userspace */ 461 case TWEIO_COMMAND: 462 /* get a request */ | 476 union twe_statrequest *ts = (union twe_statrequest *)addr; 477 TWE_Param *param; 478 void *data; 479 int *arg = (int *)addr; 480 struct twe_request *tr; 481 u_int8_t srid; 482 int s, error; 483 484 error = 0; 485 switch(cmd) { 486 /* handle a command from userspace */ 487 case TWEIO_COMMAND: 488 /* get a request */ |
463 if (twe_get_request(sc, &tr)) { 464 error = EBUSY; 465 goto cmd_done; 466 } | 489 while (twe_get_request(sc, &tr)) 490 tsleep(NULL, PPAUSE, "twioctl", hz); |
467 468 /* 469 * Save the command's request ID, copy the user-supplied command in, 470 * restore the request ID. 471 */ 472 srid = tr->tr_command.generic.request_id; 473 bcopy(&tu->tu_command, &tr->tr_command, sizeof(TWE_Command)); 474 tr->tr_command.generic.request_id = srid; 475 | 491 492 /* 493 * Save the command's request ID, copy the user-supplied command in, 494 * restore the request ID. 495 */ 496 srid = tr->tr_command.generic.request_id; 497 bcopy(&tu->tu_command, &tr->tr_command, sizeof(TWE_Command)); 498 tr->tr_command.generic.request_id = srid; 499 |
476 /* if there's a data buffer, allocate and copy it in */ 477 tr->tr_length = tu->tu_size; | 500 /* 501 * if there's a data buffer, allocate and copy it in. 502 * Must be in multipled of 512 bytes. 503 */ 504 tr->tr_length = (tu->tu_size + 511) & ~511; |
478 if (tr->tr_length > 0) { 479 if ((tr->tr_data = malloc(tr->tr_length, M_DEVBUF, M_WAITOK)) == NULL) { 480 error = ENOMEM; 481 goto cmd_done; 482 } | 505 if (tr->tr_length > 0) { 506 if ((tr->tr_data = malloc(tr->tr_length, M_DEVBUF, M_WAITOK)) == NULL) { 507 error = ENOMEM; 508 goto cmd_done; 509 } |
483 if ((error = copyin(tu->tu_data, tr->tr_data, tr->tr_length)) != 0) | 510 if ((error = copyin(tu->tu_data, tr->tr_data, tu->tu_size)) != 0) |
484 goto cmd_done; 485 tr->tr_flags |= TWE_CMD_DATAIN | TWE_CMD_DATAOUT; 486 } 487 488 /* run the command */ 489 twe_map_request(tr); 490 twe_wait_request(tr); 491 492 /* copy the command out again */ 493 bcopy(&tr->tr_command, &tu->tu_command, sizeof(TWE_Command)); 494 495 /* if there was a data buffer, copy it out */ 496 if (tr->tr_length > 0) | 511 goto cmd_done; 512 tr->tr_flags |= TWE_CMD_DATAIN | TWE_CMD_DATAOUT; 513 } 514 515 /* run the command */ 516 twe_map_request(tr); 517 twe_wait_request(tr); 518 519 /* copy the command out again */ 520 bcopy(&tr->tr_command, &tu->tu_command, sizeof(TWE_Command)); 521 522 /* if there was a data buffer, copy it out */ 523 if (tr->tr_length > 0) |
497 error = copyout(tr->tr_data, tu->tu_data, tr->tr_length); | 524 error = copyout(tr->tr_data, tu->tu_data, tu->tu_size); |
498 499 cmd_done: 500 /* free resources */ 501 if (tr->tr_data != NULL) 502 free(tr->tr_data, M_DEVBUF); 503 if (tr != NULL) 504 twe_release_request(tr); 505 --- 15 unchanged lines hidden (view full) --- 521 error = ENOENT; 522 break; 523 } 524 break; 525 526 /* poll for an AEN */ 527 case TWEIO_AEN_POLL: 528 *arg = twe_dequeue_aen(sc); | 525 526 cmd_done: 527 /* free resources */ 528 if (tr->tr_data != NULL) 529 free(tr->tr_data, M_DEVBUF); 530 if (tr != NULL) 531 twe_release_request(tr); 532 --- 15 unchanged lines hidden (view full) --- 548 error = ENOENT; 549 break; 550 } 551 break; 552 553 /* poll for an AEN */ 554 case TWEIO_AEN_POLL: 555 *arg = twe_dequeue_aen(sc); |
529 if (*arg == -1) 530 error = ENOENT; | |
531 break; 532 533 /* wait for another AEN to show up */ 534 case TWEIO_AEN_WAIT: 535 s = splbio(); | 556 break; 557 558 /* wait for another AEN to show up */ 559 case TWEIO_AEN_WAIT: 560 s = splbio(); |
536 while ((*arg = twe_dequeue_aen(sc)) == -1) { | 561 while ((*arg = twe_dequeue_aen(sc)) == TWE_AEN_QUEUE_EMPTY) { |
537 error = tsleep(&sc->twe_aen_queue, PRIBIO | PCATCH, "tweaen", 0); 538 if (error == EINTR) 539 break; 540 } 541 splx(s); 542 break; 543 544 case TWEIO_GET_PARAM: --- 23 unchanged lines hidden (view full) --- 568 free(data, M_DEVBUF); 569 } 570 break; 571 572 case TWEIO_RESET: 573 twe_reset(sc); 574 break; 575 | 562 error = tsleep(&sc->twe_aen_queue, PRIBIO | PCATCH, "tweaen", 0); 563 if (error == EINTR) 564 break; 565 } 566 splx(s); 567 break; 568 569 case TWEIO_GET_PARAM: --- 23 unchanged lines hidden (view full) --- 593 free(data, M_DEVBUF); 594 } 595 break; 596 597 case TWEIO_RESET: 598 twe_reset(sc); 599 break; 600 |
601 case TWEIO_ADD_UNIT: 602 twe_add_unit(sc, td->td_unit); 603 break; 604 605 case TWEIO_DEL_UNIT: 606 twe_del_unit(sc, td->td_unit); 607 break; 608 |
|
576 /* XXX implement ATA PASSTHROUGH */ 577 578 /* nothing we understand */ 579 default: 580 error = ENOTTY; 581 } 582 583 return(error); --- 805 unchanged lines hidden (view full) --- 1389static int 1390twe_dequeue_aen(struct twe_softc *sc) 1391{ 1392 int result; 1393 1394 debug_called(4); 1395 1396 if (sc->twe_aen_tail == sc->twe_aen_head) { | 609 /* XXX implement ATA PASSTHROUGH */ 610 611 /* nothing we understand */ 612 default: 613 error = ENOTTY; 614 } 615 616 return(error); --- 805 unchanged lines hidden (view full) --- 1422static int 1423twe_dequeue_aen(struct twe_softc *sc) 1424{ 1425 int result; 1426 1427 debug_called(4); 1428 1429 if (sc->twe_aen_tail == sc->twe_aen_head) { |
1397 result = -1; | 1430 result = TWE_AEN_QUEUE_EMPTY; |
1398 } else { 1399 result = sc->twe_aen_queue[sc->twe_aen_tail]; 1400 sc->twe_aen_tail = ((sc->twe_aen_tail + 1) % TWE_Q_LENGTH); 1401 } 1402 return(result); 1403} 1404 1405/******************************************************************************** --- 403 unchanged lines hidden --- | 1431 } else { 1432 result = sc->twe_aen_queue[sc->twe_aen_tail]; 1433 sc->twe_aen_tail = ((sc->twe_aen_tail + 1) % TWE_Q_LENGTH); 1434 } 1435 return(result); 1436} 1437 1438/******************************************************************************** --- 403 unchanged lines hidden --- |