Deleted Added
full compact
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 ---