Lines 112-124
typedef enum {
Link Here
|
112 |
CD_FLAG_RETRY_UA = 0x0200, |
112 |
CD_FLAG_RETRY_UA = 0x0200, |
113 |
CD_FLAG_VALID_MEDIA = 0x0400, |
113 |
CD_FLAG_VALID_MEDIA = 0x0400, |
114 |
CD_FLAG_VALID_TOC = 0x0800, |
114 |
CD_FLAG_VALID_TOC = 0x0800, |
115 |
CD_FLAG_SCTX_INIT = 0x1000 |
115 |
CD_FLAG_SCTX_INIT = 0x1000, |
|
|
116 |
CD_FLAG_MEDIA_WAIT = 0x2000, |
117 |
CD_FLAG_MEDIA_SCAN_ACT = 0x4000 |
116 |
} cd_flags; |
118 |
} cd_flags; |
117 |
|
119 |
|
118 |
typedef enum { |
120 |
typedef enum { |
119 |
CD_CCB_PROBE = 0x01, |
121 |
CD_CCB_PROBE = 0x01, |
120 |
CD_CCB_BUFFER_IO = 0x02, |
122 |
CD_CCB_BUFFER_IO = 0x02, |
121 |
CD_CCB_TUR = 0x04, |
123 |
CD_CCB_TUR = 0x03, |
|
|
124 |
CD_CCB_MEDIA_PREVENT = 0x04, |
125 |
CD_CCB_MEDIA_ALLOW = 0x05, |
126 |
CD_CCB_MEDIA_SIZE = 0x06, |
127 |
CD_CCB_MEDIA_TOC_HDR = 0x07, |
128 |
CD_CCB_MEDIA_TOC_FULL = 0x08, |
129 |
CD_CCB_MEDIA_TOC_LEAD = 0x09, |
122 |
CD_CCB_TYPE_MASK = 0x0F, |
130 |
CD_CCB_TYPE_MASK = 0x0F, |
123 |
CD_CCB_RETRY_UA = 0x10 |
131 |
CD_CCB_RETRY_UA = 0x10 |
124 |
} cd_ccb_state; |
132 |
} cd_ccb_state; |
Lines 138-144
struct cd_toc_single {
Link Here
|
138 |
|
146 |
|
139 |
typedef enum { |
147 |
typedef enum { |
140 |
CD_STATE_PROBE, |
148 |
CD_STATE_PROBE, |
141 |
CD_STATE_NORMAL |
149 |
CD_STATE_NORMAL, |
|
|
150 |
CD_STATE_MEDIA_PREVENT, |
151 |
CD_STATE_MEDIA_ALLOW, |
152 |
CD_STATE_MEDIA_SIZE, |
153 |
CD_STATE_MEDIA_TOC_HDR, |
154 |
CD_STATE_MEDIA_TOC_FULL, |
155 |
CD_STATE_MEDIA_TOC_LEAD |
142 |
} cd_state; |
156 |
} cd_state; |
143 |
|
157 |
|
144 |
struct cd_softc { |
158 |
struct cd_softc { |
Lines 159-164
struct cd_softc {
Link Here
|
159 |
struct sysctl_oid *sysctl_tree; |
173 |
struct sysctl_oid *sysctl_tree; |
160 |
STAILQ_HEAD(, cd_mode_params) mode_queue; |
174 |
STAILQ_HEAD(, cd_mode_params) mode_queue; |
161 |
struct cd_tocdata toc; |
175 |
struct cd_tocdata toc; |
|
|
176 |
int toc_read_len; |
177 |
struct cd_toc_single leadout; |
162 |
struct disk *disk; |
178 |
struct disk *disk; |
163 |
struct callout mediapoll_c; |
179 |
struct callout mediapoll_c; |
164 |
|
180 |
|
Lines 233-239
static void cddone(struct cam_periph *periph,
Link Here
|
233 |
static union cd_pages *cdgetpage(struct cd_mode_params *mode_params); |
249 |
static union cd_pages *cdgetpage(struct cd_mode_params *mode_params); |
234 |
static int cdgetpagesize(int page_num); |
250 |
static int cdgetpagesize(int page_num); |
235 |
static void cdprevent(struct cam_periph *periph, int action); |
251 |
static void cdprevent(struct cam_periph *periph, int action); |
236 |
static int cdcheckmedia(struct cam_periph *periph); |
252 |
static void cdmediaprobedone(struct cam_periph *periph); |
|
|
253 |
static int cdcheckmedia(struct cam_periph *periph, int do_wait); |
237 |
static int cdsize(struct cam_periph *periph, u_int32_t *size); |
254 |
static int cdsize(struct cam_periph *periph, u_int32_t *size); |
238 |
static int cd6byteworkaround(union ccb *ccb); |
255 |
static int cd6byteworkaround(union ccb *ccb); |
239 |
static int cderror(union ccb *ccb, u_int32_t cam_flags, |
256 |
static int cderror(union ccb *ccb, u_int32_t cam_flags, |
Lines 742-748
cdopen(struct disk *dp)
Link Here
|
742 |
* if we don't have media, but then we don't allow anything but the |
759 |
* if we don't have media, but then we don't allow anything but the |
743 |
* CDIOCEJECT/CDIOCCLOSE ioctls if there is no media. |
760 |
* CDIOCEJECT/CDIOCCLOSE ioctls if there is no media. |
744 |
*/ |
761 |
*/ |
745 |
cdcheckmedia(periph); |
762 |
cdcheckmedia(periph, /*do_wait*/ 1); |
746 |
|
763 |
|
747 |
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdopen\n")); |
764 |
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdopen\n")); |
748 |
cam_periph_unhold(periph); |
765 |
cam_periph_unhold(periph); |
Lines 838-864
cdstrategy(struct bio *bp)
Link Here
|
838 |
return; |
855 |
return; |
839 |
} |
856 |
} |
840 |
|
857 |
|
841 |
/* |
|
|
842 |
* If we don't have valid media, look for it before trying to |
843 |
* schedule the I/O. |
844 |
*/ |
845 |
if ((softc->flags & CD_FLAG_VALID_MEDIA) == 0) { |
846 |
int error; |
847 |
|
848 |
error = cdcheckmedia(periph); |
849 |
if (error != 0) { |
850 |
cam_periph_unlock(periph); |
851 |
biofinish(bp, NULL, error); |
852 |
return; |
853 |
} |
854 |
} |
855 |
|
856 |
/* |
858 |
/* |
857 |
* Place it in the queue of disk activities for this disk |
859 |
* Place it in the queue of disk activities for this disk |
858 |
*/ |
860 |
*/ |
859 |
bioq_disksort(&softc->bio_queue, bp); |
861 |
bioq_disksort(&softc->bio_queue, bp); |
860 |
|
862 |
|
861 |
xpt_schedule(periph, CAM_PRIORITY_NORMAL); |
863 |
/* |
|
|
864 |
* If we don't know that we have valid media, schedule the media |
865 |
* check first. The I/O will get executed after the media check. |
866 |
*/ |
867 |
if ((softc->flags & CD_FLAG_VALID_MEDIA) == 0) |
868 |
cdcheckmedia(periph, /*do_wait*/ 0); |
869 |
else |
870 |
xpt_schedule(periph, CAM_PRIORITY_NORMAL); |
862 |
|
871 |
|
863 |
cam_periph_unlock(periph); |
872 |
cam_periph_unlock(periph); |
864 |
return; |
873 |
return; |
Lines 870-876
cdstart(struct cam_periph *periph, union ccb *star
Link Here
|
870 |
struct cd_softc *softc; |
879 |
struct cd_softc *softc; |
871 |
struct bio *bp; |
880 |
struct bio *bp; |
872 |
struct ccb_scsiio *csio; |
881 |
struct ccb_scsiio *csio; |
873 |
struct scsi_read_capacity_data *rcap; |
|
|
874 |
|
882 |
|
875 |
softc = (struct cd_softc *)periph->softc; |
883 |
softc = (struct cd_softc *)periph->softc; |
876 |
|
884 |
|
Lines 951-966
cdstart(struct cam_periph *periph, union ccb *star
Link Here
|
951 |
break; |
959 |
break; |
952 |
} |
960 |
} |
953 |
case CD_STATE_PROBE: |
961 |
case CD_STATE_PROBE: |
|
|
962 |
case CD_STATE_MEDIA_SIZE: |
954 |
{ |
963 |
{ |
|
|
964 |
struct scsi_read_capacity_data *rcap; |
955 |
|
965 |
|
956 |
rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap), |
966 |
rcap = (struct scsi_read_capacity_data *)malloc(sizeof(*rcap), |
957 |
M_SCSICD, M_NOWAIT | M_ZERO); |
967 |
M_SCSICD, M_NOWAIT | M_ZERO); |
958 |
if (rcap == NULL) { |
968 |
if (rcap == NULL) { |
959 |
xpt_print(periph->path, |
969 |
xpt_print(periph->path, |
960 |
"cdstart: Couldn't malloc read_capacity data\n"); |
970 |
"%s: Couldn't malloc read_capacity data\n", |
961 |
/* cd_free_periph??? */ |
971 |
__func__); |
|
|
972 |
xpt_release_ccb(start_ccb); |
973 |
/* |
974 |
* We can't probe because we can't allocate memory, |
975 |
* so invalidate the peripheral. The system probably |
976 |
* has larger problems at this stage. If we've |
977 |
* already probed (and are re-probing capacity), we |
978 |
* don't need to invalidate. |
979 |
* |
980 |
* XXX KDM need to reset probe state and kick out |
981 |
* pending I/O. |
982 |
*/ |
983 |
if (softc->state == CD_STATE_PROBE) |
984 |
cam_periph_invalidate(periph); |
962 |
break; |
985 |
break; |
963 |
} |
986 |
} |
|
|
987 |
|
988 |
/* |
989 |
* Set the default capacity and sector size to something that |
990 |
* GEOM can handle. This will get reset when a read capacity |
991 |
* completes successfully. |
992 |
*/ |
993 |
softc->disk->d_sectorsize = 2048; |
994 |
softc->disk->d_mediasize = 0; |
995 |
|
964 |
csio = &start_ccb->csio; |
996 |
csio = &start_ccb->csio; |
965 |
scsi_read_capacity(csio, |
997 |
scsi_read_capacity(csio, |
966 |
/*retries*/ cd_retry_count, |
998 |
/*retries*/ cd_retry_count, |
Lines 970-980
cdstart(struct cam_periph *periph, union ccb *star
Link Here
|
970 |
SSD_FULL_SIZE, |
1002 |
SSD_FULL_SIZE, |
971 |
/*timeout*/20000); |
1003 |
/*timeout*/20000); |
972 |
start_ccb->ccb_h.ccb_bp = NULL; |
1004 |
start_ccb->ccb_h.ccb_bp = NULL; |
973 |
start_ccb->ccb_h.ccb_state = CD_CCB_PROBE; |
1005 |
if (softc->state == CD_STATE_PROBE) |
|
|
1006 |
start_ccb->ccb_h.ccb_state = CD_CCB_PROBE; |
1007 |
else |
1008 |
start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_SIZE; |
974 |
xpt_action(start_ccb); |
1009 |
xpt_action(start_ccb); |
975 |
break; |
1010 |
break; |
976 |
} |
1011 |
} |
|
|
1012 |
case CD_STATE_MEDIA_ALLOW: |
1013 |
case CD_STATE_MEDIA_PREVENT: |
1014 |
{ |
1015 |
/* |
1016 |
* If the CD is already locked, we don't need to do this. |
1017 |
* Move on to the capacity check. |
1018 |
*/ |
1019 |
if ((softc->flags & CD_FLAG_DISC_LOCKED) != 0) { |
1020 |
softc->state = CD_STATE_MEDIA_SIZE; |
1021 |
xpt_release_ccb(start_ccb); |
1022 |
xpt_schedule(periph, CAM_PRIORITY_NORMAL); |
1023 |
break; |
1024 |
} |
1025 |
|
1026 |
scsi_prevent(&start_ccb->csio, |
1027 |
/*retries*/ cd_retry_count, |
1028 |
/*cbfcnp*/ cddone, |
1029 |
/*tag_action*/ MSG_SIMPLE_Q_TAG, |
1030 |
/*action*/ (softc->state == CD_STATE_MEDIA_ALLOW) ? |
1031 |
PR_ALLOW : PR_PREVENT, |
1032 |
/*sense_len*/ SSD_FULL_SIZE, |
1033 |
/*timeout*/ 60000); |
1034 |
|
1035 |
start_ccb->ccb_h.ccb_bp = NULL; |
1036 |
if (softc->state == CD_STATE_MEDIA_ALLOW) |
1037 |
start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_ALLOW; |
1038 |
else |
1039 |
start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_PREVENT; |
1040 |
xpt_action(start_ccb); |
1041 |
break; |
977 |
} |
1042 |
} |
|
|
1043 |
case CD_STATE_MEDIA_TOC_HDR: { |
1044 |
struct ioc_toc_header *toch; |
1045 |
|
1046 |
bzero(&softc->toc, sizeof(softc->toc)); |
1047 |
|
1048 |
toch = &softc->toc.header; |
1049 |
|
1050 |
scsi_read_toc(&start_ccb->csio, |
1051 |
/*retries*/ cd_retry_count, |
1052 |
/*cbfcnp*/ cddone, |
1053 |
/*tag_action*/ MSG_SIMPLE_Q_TAG, |
1054 |
/*byte1_flags*/ 0, |
1055 |
/*format*/ SRTOC_FORMAT_TOC, |
1056 |
/*track*/ 0, |
1057 |
/*data_ptr*/ (uint8_t *)toch, |
1058 |
/*dxfer_len*/ sizeof(*toch), |
1059 |
/*sense_len*/ SSD_FULL_SIZE, |
1060 |
/*timeout*/ 50000); |
1061 |
start_ccb->ccb_h.ccb_bp = NULL; |
1062 |
start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_TOC_HDR; |
1063 |
xpt_action(start_ccb); |
1064 |
break; |
1065 |
} |
1066 |
case CD_STATE_MEDIA_TOC_FULL: { |
1067 |
|
1068 |
bzero(&softc->toc, sizeof(softc->toc)); |
1069 |
|
1070 |
scsi_read_toc(&start_ccb->csio, |
1071 |
/*retries*/ cd_retry_count, |
1072 |
/*cbfcnp*/ cddone, |
1073 |
/*tag_action*/ MSG_SIMPLE_Q_TAG, |
1074 |
/*byte1_flags*/ 0, |
1075 |
/*format*/ SRTOC_FORMAT_TOC, |
1076 |
/*track*/ 0, |
1077 |
/*data_ptr*/ (uint8_t *)&softc->toc, |
1078 |
/*dxfer_len*/ softc->toc_read_len ? |
1079 |
softc->toc_read_len : |
1080 |
sizeof(softc->toc), |
1081 |
/*sense_len*/ SSD_FULL_SIZE, |
1082 |
/*timeout*/ 50000); |
1083 |
start_ccb->ccb_h.ccb_bp = NULL; |
1084 |
start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_TOC_FULL; |
1085 |
xpt_action(start_ccb); |
1086 |
break; |
1087 |
} |
1088 |
case CD_STATE_MEDIA_TOC_LEAD: { |
1089 |
struct cd_toc_single *leadout; |
1090 |
|
1091 |
leadout = &softc->leadout; |
1092 |
bzero(leadout, sizeof(*leadout)); |
1093 |
|
1094 |
scsi_read_toc(&start_ccb->csio, |
1095 |
/*retries*/ cd_retry_count, |
1096 |
/*cbfcnp*/ cddone, |
1097 |
/*tag_action*/ MSG_SIMPLE_Q_TAG, |
1098 |
/*byte1_flags*/ CD_MSF, |
1099 |
/*format*/ SRTOC_FORMAT_TOC, |
1100 |
/*track*/ LEADOUT, |
1101 |
/*data_ptr*/ (uint8_t *)leadout, |
1102 |
/*dxfer_len*/ sizeof(*leadout), |
1103 |
/*sense_len*/ SSD_FULL_SIZE, |
1104 |
/*timeout*/ 50000); |
1105 |
start_ccb->ccb_h.ccb_bp = NULL; |
1106 |
start_ccb->ccb_h.ccb_state = CD_CCB_MEDIA_TOC_LEAD; |
1107 |
xpt_action(start_ccb); |
1108 |
break; |
1109 |
} |
1110 |
} |
978 |
} |
1111 |
} |
979 |
|
1112 |
|
980 |
static void |
1113 |
static void |
Lines 1238-1243
cddone(struct cam_periph *periph, union ccb *done_
Link Here
|
1238 |
cam_periph_release_locked(periph); |
1371 |
cam_periph_release_locked(periph); |
1239 |
return; |
1372 |
return; |
1240 |
} |
1373 |
} |
|
|
1374 |
case CD_CCB_MEDIA_ALLOW: |
1375 |
case CD_CCB_MEDIA_PREVENT: |
1376 |
{ |
1377 |
int error; |
1378 |
int is_prevent; |
1379 |
|
1380 |
error = 0; |
1381 |
|
1382 |
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { |
1383 |
error = cderror(done_ccb, CAM_RETRY_SELTO, |
1384 |
SF_RETRY_UA | SF_NO_PRINT); |
1385 |
} |
1386 |
if (error == ERESTART) |
1387 |
return; |
1388 |
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) |
1389 |
cam_release_devq(done_ccb->ccb_h.path, |
1390 |
/*relsim_flags*/0, |
1391 |
/*reduction*/0, |
1392 |
/*timeout*/0, |
1393 |
/*getcount_only*/0); |
1394 |
|
1395 |
/* |
1396 |
* Note that just like the original cdcheckmedia(), we do |
1397 |
* a prevent without failing the whole operation if the |
1398 |
* prevent fails. We try, but keep going if it doesn't |
1399 |
* work. |
1400 |
*/ |
1401 |
|
1402 |
if ((done_ccb->ccb_h.ccb_state & CD_CCB_TYPE_MASK) == |
1403 |
CD_CCB_MEDIA_PREVENT) |
1404 |
is_prevent = 1; |
1405 |
else |
1406 |
is_prevent = 0; |
1407 |
|
1408 |
xpt_release_ccb(done_ccb); |
1409 |
|
1410 |
if (is_prevent != 0) { |
1411 |
if (error == 0) |
1412 |
softc->flags |= CD_FLAG_DISC_LOCKED; |
1413 |
else |
1414 |
softc->flags &= ~CD_FLAG_DISC_LOCKED; |
1415 |
softc->state = CD_STATE_MEDIA_SIZE; |
1416 |
xpt_schedule(periph, CAM_PRIORITY_NORMAL); |
1417 |
} else { |
1418 |
if (error == 0) |
1419 |
softc->flags &= ~CD_FLAG_DISC_LOCKED; |
1420 |
softc->state = CD_STATE_NORMAL; |
1421 |
if (bioq_first(&softc->bio_queue) != NULL) |
1422 |
xpt_schedule(periph, CAM_PRIORITY_NORMAL); |
1423 |
} |
1424 |
return; |
1425 |
} |
1426 |
case CD_CCB_MEDIA_SIZE: |
1427 |
{ |
1428 |
struct scsi_read_capacity_data *rdcap; |
1429 |
int error; |
1430 |
|
1431 |
error = 0; |
1432 |
if ((csio->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { |
1433 |
error = cderror(done_ccb, CAM_RETRY_SELTO, |
1434 |
SF_RETRY_UA | SF_NO_PRINT); |
1435 |
} |
1436 |
if (error == ERESTART) |
1437 |
return; |
1438 |
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) |
1439 |
cam_release_devq(done_ccb->ccb_h.path, |
1440 |
/*relsim_flags*/0, |
1441 |
/*reduction*/0, |
1442 |
/*timeout*/0, |
1443 |
/*getcount_only*/0); |
1444 |
rdcap = (struct scsi_read_capacity_data *)csio->data_ptr; |
1445 |
|
1446 |
if (error == 0) { |
1447 |
softc->params.disksize =scsi_4btoul(rdcap->addr) + 1; |
1448 |
softc->params.blksize = scsi_4btoul(rdcap->length); |
1449 |
|
1450 |
/* Make sure we got at least some block size. */ |
1451 |
if (softc->params.blksize == 0) |
1452 |
error = EIO; |
1453 |
/* |
1454 |
* SCSI-3 mandates that the reported blocksize shall be |
1455 |
* 2048. Older drives sometimes report funny values, |
1456 |
* trim it down to 2048, or other parts of the kernel |
1457 |
* will get confused. |
1458 |
* |
1459 |
* XXX we leave drives alone that might report 512 |
1460 |
* bytes, as well as drives reporting more weird |
1461 |
* sizes like perhaps 4K. |
1462 |
*/ |
1463 |
if (softc->params.blksize > 2048 |
1464 |
&& softc->params.blksize <= 2352) |
1465 |
softc->params.blksize = 2048; |
1466 |
} |
1467 |
free(rdcap, M_SCSICD); |
1468 |
|
1469 |
if (error == 0) { |
1470 |
softc->disk->d_sectorsize = softc->params.blksize; |
1471 |
softc->disk->d_mediasize = |
1472 |
(off_t)softc->params.blksize * |
1473 |
softc->params.disksize; |
1474 |
softc->flags |= CD_FLAG_SAW_MEDIA | CD_FLAG_VALID_MEDIA; |
1475 |
softc->state = CD_STATE_MEDIA_TOC_HDR; |
1476 |
} else { |
1477 |
softc->flags &= ~(CD_FLAG_VALID_MEDIA | |
1478 |
CD_FLAG_VALID_TOC); |
1479 |
bioq_flush(&softc->bio_queue, NULL, EINVAL); |
1480 |
softc->state = CD_STATE_MEDIA_ALLOW; |
1481 |
cdmediaprobedone(periph); |
1482 |
} |
1483 |
xpt_release_ccb(done_ccb); |
1484 |
xpt_schedule(periph, CAM_PRIORITY_NORMAL); |
1485 |
return; |
1486 |
} |
1487 |
case CD_CCB_MEDIA_TOC_HDR: |
1488 |
case CD_CCB_MEDIA_TOC_FULL: |
1489 |
case CD_CCB_MEDIA_TOC_LEAD: |
1490 |
{ |
1491 |
int error; |
1492 |
struct ioc_toc_header *toch; |
1493 |
int num_entries; |
1494 |
int cdindex; |
1495 |
|
1496 |
error = 0; |
1497 |
|
1498 |
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { |
1499 |
error = cderror(done_ccb, CAM_RETRY_SELTO, |
1500 |
SF_RETRY_UA | SF_NO_PRINT); |
1501 |
} |
1502 |
if (error == ERESTART) |
1503 |
return; |
1504 |
|
1505 |
if ((done_ccb->ccb_h.status & CAM_DEV_QFRZN) != 0) |
1506 |
cam_release_devq(done_ccb->ccb_h.path, |
1507 |
/*relsim_flags*/0, |
1508 |
/*reduction*/0, |
1509 |
/*timeout*/0, |
1510 |
/*getcount_only*/0); |
1511 |
|
1512 |
/* |
1513 |
* We will get errors here for media that doesn't have a table |
1514 |
* of contents. According to the MMC-3 spec: "When a Read |
1515 |
* TOC/PMA/ATIP command is presented for a DDCD/CD-R/RW media, |
1516 |
* where the first TOC has not been recorded (no complete |
1517 |
* session) and the Format codes 0000b, 0001b, or 0010b are |
1518 |
* specified, this command shall be rejected with an INVALID |
1519 |
* FIELD IN CDB. Devices that are not capable of reading an |
1520 |
* incomplete session on DDC/CD-R/RW media shall report |
1521 |
* CANNOT READ MEDIUM - INCOMPATIBLE FORMAT." |
1522 |
* |
1523 |
* So this isn't fatal if we can't read the table of contents, |
1524 |
* it just means that the user won't be able to issue the |
1525 |
* play tracks ioctl, and likely lots of other stuff won't |
1526 |
* work either. They need to burn the CD before we can do |
1527 |
* a whole lot with it. So we don't print anything here if |
1528 |
* we get an error back. |
1529 |
* |
1530 |
* We also bail out if the drive doesn't at least give us |
1531 |
* the full TOC header. |
1532 |
*/ |
1533 |
if ((error != 0) |
1534 |
|| ((csio->dxfer_len - csio->resid) < |
1535 |
sizeof(struct ioc_toc_header))) { |
1536 |
softc->flags &= ~CD_FLAG_VALID_TOC; |
1537 |
bzero(&softc->toc, sizeof(softc->toc)); |
1538 |
/* |
1539 |
* Failing the TOC read is not an error. |
1540 |
*/ |
1541 |
softc->state = CD_STATE_NORMAL; |
1542 |
xpt_release_ccb(done_ccb); |
1543 |
|
1544 |
cdmediaprobedone(periph); |
1545 |
|
1546 |
/* |
1547 |
* Go ahead and schedule I/O execution if there is |
1548 |
* anything in the queue. It'll probably get |
1549 |
* kicked out with an error. |
1550 |
*/ |
1551 |
if (bioq_first(&softc->bio_queue) != NULL) |
1552 |
xpt_schedule(periph, CAM_PRIORITY_NORMAL); |
1553 |
return; |
1554 |
} |
1555 |
|
1556 |
/* |
1557 |
* Note that this is NOT the storage location used for the |
1558 |
* leadout! |
1559 |
*/ |
1560 |
toch = &softc->toc.header; |
1561 |
|
1562 |
if (softc->quirks & CD_Q_BCD_TRACKS) { |
1563 |
toch->starting_track = bcd2bin(toch->starting_track); |
1564 |
toch->ending_track = bcd2bin(toch->ending_track); |
1565 |
} |
1566 |
|
1567 |
/* Number of TOC entries, plus leadout */ |
1568 |
num_entries = (toch->ending_track - toch->starting_track) + 2; |
1569 |
cdindex = toch->starting_track + num_entries -1; |
1570 |
|
1571 |
if ((done_ccb->ccb_h.ccb_state & CD_CCB_TYPE_MASK) == |
1572 |
CD_CCB_MEDIA_TOC_HDR) { |
1573 |
if (num_entries <= 0) { |
1574 |
softc->flags &= ~CD_FLAG_VALID_TOC; |
1575 |
bzero(&softc->toc, sizeof(softc->toc)); |
1576 |
/* |
1577 |
* Failing the TOC read is not an error. |
1578 |
*/ |
1579 |
softc->state = CD_STATE_NORMAL; |
1580 |
xpt_release_ccb(done_ccb); |
1581 |
|
1582 |
cdmediaprobedone(periph); |
1583 |
|
1584 |
/* |
1585 |
* Go ahead and schedule I/O execution if |
1586 |
* there is anything in the queue. It'll |
1587 |
* probably get kicked out with an error. |
1588 |
*/ |
1589 |
if (bioq_first(&softc->bio_queue) != NULL) |
1590 |
xpt_schedule(periph, |
1591 |
CAM_PRIORITY_NORMAL); |
1592 |
} else { |
1593 |
softc->toc_read_len = num_entries * |
1594 |
sizeof(struct cd_toc_entry); |
1595 |
softc->toc_read_len += sizeof(*toch); |
1596 |
|
1597 |
softc->state = CD_STATE_MEDIA_TOC_FULL; |
1598 |
xpt_release_ccb(done_ccb); |
1599 |
xpt_schedule(periph, CAM_PRIORITY_NORMAL); |
1600 |
} |
1601 |
|
1602 |
return; |
1603 |
} else if ((done_ccb->ccb_h.ccb_state & CD_CCB_TYPE_MASK) == |
1604 |
CD_CCB_MEDIA_TOC_LEAD) { |
1605 |
struct cd_toc_single *leadout; |
1606 |
|
1607 |
leadout = (struct cd_toc_single *)csio->data_ptr; |
1608 |
softc->toc.entries[cdindex - toch->starting_track] = |
1609 |
leadout->entry; |
1610 |
} else if (((done_ccb->ccb_h.ccb_state & CD_CCB_TYPE_MASK) == |
1611 |
CD_CCB_MEDIA_TOC_FULL) |
1612 |
&& (cdindex == toch->ending_track + 1)) { |
1613 |
/* |
1614 |
* XXX KDM is this necessary? Probably only if the |
1615 |
* drive doesn't return leadout information with the |
1616 |
* table of contents. |
1617 |
*/ |
1618 |
softc->state = CD_STATE_MEDIA_TOC_LEAD; |
1619 |
xpt_release_ccb(done_ccb); |
1620 |
xpt_schedule(periph, CAM_PRIORITY_NORMAL); |
1621 |
return; |
1622 |
} |
1623 |
|
1624 |
if (softc->quirks & CD_Q_BCD_TRACKS) { |
1625 |
for (cdindex = 0; cdindex < num_entries - 1; cdindex++){ |
1626 |
softc->toc.entries[cdindex].track = |
1627 |
bcd2bin(softc->toc.entries[cdindex].track); |
1628 |
} |
1629 |
} |
1630 |
|
1631 |
softc->flags |= CD_FLAG_VALID_TOC; |
1632 |
/* If the first track is audio, correct sector size. */ |
1633 |
if ((softc->toc.entries[0].control & 4) == 0) { |
1634 |
softc->disk->d_sectorsize =softc->params.blksize = 2352; |
1635 |
softc->disk->d_mediasize = |
1636 |
(off_t)softc->params.blksize * |
1637 |
softc->params.disksize; |
1638 |
} |
1639 |
softc->state = CD_STATE_NORMAL; |
1640 |
|
1641 |
/* |
1642 |
* We unconditionally (re)set the blocksize each time the |
1643 |
* CD device is opened. This is because the CD can change, |
1644 |
* and therefore the blocksize might change. |
1645 |
* XXX problems here if some slice or partition is still |
1646 |
* open with the old size? |
1647 |
*/ |
1648 |
if ((softc->disk->d_devstat->flags & DEVSTAT_BS_UNAVAILABLE)!=0) |
1649 |
softc->disk->d_devstat->flags &= |
1650 |
~DEVSTAT_BS_UNAVAILABLE; |
1651 |
softc->disk->d_devstat->block_size = softc->params.blksize; |
1652 |
|
1653 |
xpt_release_ccb(done_ccb); |
1654 |
|
1655 |
cdmediaprobedone(periph); |
1656 |
|
1657 |
if (bioq_first(&softc->bio_queue) != NULL) |
1658 |
xpt_schedule(periph, CAM_PRIORITY_NORMAL); |
1659 |
return; |
1660 |
} |
1241 |
default: |
1661 |
default: |
1242 |
break; |
1662 |
break; |
1243 |
} |
1663 |
} |
Lines 1307-1313
cdioctl(struct disk *dp, u_long cmd, void *addr, i
Link Here
|
1307 |
&& ((cmd != CDIOCCLOSE) |
1727 |
&& ((cmd != CDIOCCLOSE) |
1308 |
&& (cmd != CDIOCEJECT)) |
1728 |
&& (cmd != CDIOCEJECT)) |
1309 |
&& (IOCGROUP(cmd) == 'c')) { |
1729 |
&& (IOCGROUP(cmd) == 'c')) { |
1310 |
error = cdcheckmedia(periph); |
1730 |
error = cdcheckmedia(periph, /*do_wait*/ 1); |
1311 |
if (error != 0) { |
1731 |
if (error != 0) { |
1312 |
cam_periph_unhold(periph); |
1732 |
cam_periph_unhold(periph); |
1313 |
cam_periph_unlock(periph); |
1733 |
cam_periph_unlock(periph); |
Lines 2197-2207
cdprevent(struct cam_periph *periph, int action)
Link Here
|
2197 |
} |
2617 |
} |
2198 |
} |
2618 |
} |
2199 |
|
2619 |
|
|
|
2620 |
static void |
2621 |
cdmediaprobedone(struct cam_periph *periph) |
2622 |
{ |
2623 |
struct cd_softc *softc; |
2624 |
|
2625 |
softc = (struct cd_softc *)periph->softc; |
2626 |
|
2627 |
softc->flags &= ~CD_FLAG_MEDIA_SCAN_ACT; |
2628 |
|
2629 |
if ((softc->flags & CD_FLAG_MEDIA_WAIT) != 0) { |
2630 |
softc->flags &= ~CD_FLAG_MEDIA_WAIT; |
2631 |
wakeup(&softc->toc); |
2632 |
} |
2633 |
} |
2634 |
|
2200 |
/* |
2635 |
/* |
2201 |
* XXX: the disk media and sector size is only really able to change |
2636 |
* XXX: the disk media and sector size is only really able to change |
2202 |
* XXX: while the device is closed. |
2637 |
* XXX: while the device is closed. |
2203 |
*/ |
2638 |
*/ |
|
|
2639 |
|
2204 |
static int |
2640 |
static int |
|
|
2641 |
cdcheckmedia(struct cam_periph *periph, int do_wait) |
2642 |
{ |
2643 |
struct cd_softc *softc; |
2644 |
int error; |
2645 |
|
2646 |
softc = (struct cd_softc *)periph->softc; |
2647 |
error = 0; |
2648 |
|
2649 |
if ((do_wait != 0) |
2650 |
&& ((softc->flags & CD_FLAG_MEDIA_WAIT) == 0)) { |
2651 |
softc->flags |= CD_FLAG_MEDIA_WAIT; |
2652 |
} |
2653 |
if ((softc->flags & CD_FLAG_MEDIA_SCAN_ACT) == 0) { |
2654 |
softc->state = CD_STATE_MEDIA_PREVENT; |
2655 |
softc->flags |= CD_FLAG_MEDIA_SCAN_ACT; |
2656 |
xpt_schedule(periph, CAM_PRIORITY_NORMAL); |
2657 |
} |
2658 |
|
2659 |
if (do_wait == 0) |
2660 |
goto bailout; |
2661 |
|
2662 |
error = msleep(&softc->toc, cam_periph_mtx(periph), PRIBIO,"cdmedia",0); |
2663 |
|
2664 |
if (error != 0) |
2665 |
goto bailout; |
2666 |
|
2667 |
/* |
2668 |
* Check to see whether we have a valid size from the media. We |
2669 |
* may or may not have a valid TOC. |
2670 |
*/ |
2671 |
if ((softc->flags & CD_FLAG_VALID_MEDIA) == 0) |
2672 |
error = EINVAL; |
2673 |
bailout: |
2674 |
|
2675 |
return (error); |
2676 |
} |
2677 |
|
2678 |
#if 0 |
2679 |
static int |
2205 |
cdcheckmedia(struct cam_periph *periph) |
2680 |
cdcheckmedia(struct cam_periph *periph) |
2206 |
{ |
2681 |
{ |
2207 |
struct cd_softc *softc; |
2682 |
struct cd_softc *softc; |
Lines 2341-2346
bailout:
Link Here
|
2341 |
|
2816 |
|
2342 |
return (error); |
2817 |
return (error); |
2343 |
} |
2818 |
} |
|
|
2819 |
#endif |
2344 |
|
2820 |
|
2345 |
static int |
2821 |
static int |
2346 |
cdsize(struct cam_periph *periph, u_int32_t *size) |
2822 |
cdsize(struct cam_periph *periph, u_int32_t *size) |
Lines 2620-2626
static int
Link Here
|
2620 |
cdreadtoc(struct cam_periph *periph, u_int32_t mode, u_int32_t start, |
3096 |
cdreadtoc(struct cam_periph *periph, u_int32_t mode, u_int32_t start, |
2621 |
u_int8_t *data, u_int32_t len, u_int32_t sense_flags) |
3097 |
u_int8_t *data, u_int32_t len, u_int32_t sense_flags) |
2622 |
{ |
3098 |
{ |
2623 |
struct scsi_read_toc *scsi_cmd; |
|
|
2624 |
u_int32_t ntoc; |
3099 |
u_int32_t ntoc; |
2625 |
struct ccb_scsiio *csio; |
3100 |
struct ccb_scsiio *csio; |
2626 |
union ccb *ccb; |
3101 |
union ccb *ccb; |
Lines 2633-2661
cdreadtoc(struct cam_periph *periph, u_int32_t mod
Link Here
|
2633 |
|
3108 |
|
2634 |
csio = &ccb->csio; |
3109 |
csio = &ccb->csio; |
2635 |
|
3110 |
|
2636 |
cam_fill_csio(csio, |
3111 |
scsi_read_toc(csio, |
2637 |
/* retries */ cd_retry_count, |
3112 |
/* retries */ cd_retry_count, |
2638 |
/* cbfcnp */ NULL, |
3113 |
/* cbfcnp */ NULL, |
2639 |
/* flags */ CAM_DIR_IN, |
|
|
2640 |
/* tag_action */ MSG_SIMPLE_Q_TAG, |
3114 |
/* tag_action */ MSG_SIMPLE_Q_TAG, |
|
|
3115 |
/* byte1_flags */ (mode == CD_MSF_FORMAT) ? CD_MSF : 0, |
3116 |
/* format */ SRTOC_FORMAT_TOC, |
3117 |
/* track*/ start, |
2641 |
/* data_ptr */ data, |
3118 |
/* data_ptr */ data, |
2642 |
/* dxfer_len */ len, |
3119 |
/* dxfer_len */ len, |
2643 |
/* sense_len */ SSD_FULL_SIZE, |
3120 |
/* sense_len */ SSD_FULL_SIZE, |
2644 |
sizeof(struct scsi_read_toc), |
3121 |
/* timeout */ 50000); |
2645 |
/* timeout */ 50000); |
|
|
2646 |
|
3122 |
|
2647 |
scsi_cmd = (struct scsi_read_toc *)&csio->cdb_io.cdb_bytes; |
|
|
2648 |
bzero (scsi_cmd, sizeof(*scsi_cmd)); |
2649 |
|
2650 |
if (mode == CD_MSF_FORMAT) |
2651 |
scsi_cmd->byte2 |= CD_MSF; |
2652 |
scsi_cmd->from_track = start; |
2653 |
/* scsi_ulto2b(ntoc, (u_int8_t *)scsi_cmd->data_len); */ |
2654 |
scsi_cmd->data_len[0] = (ntoc) >> 8; |
2655 |
scsi_cmd->data_len[1] = (ntoc) & 0xff; |
2656 |
|
2657 |
scsi_cmd->op_code = READ_TOC; |
2658 |
|
2659 |
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, |
3123 |
error = cdrunccb(ccb, cderror, /*cam_flags*/CAM_RETRY_SELTO, |
2660 |
/*sense_flags*/SF_RETRY_UA | sense_flags); |
3124 |
/*sense_flags*/SF_RETRY_UA | sense_flags); |
2661 |
|
3125 |
|
Lines 3713-3715
scsi_read_dvd_structure(struct ccb_scsiio *csio, u
Link Here
|
3713 |
sizeof(*scsi_cmd), |
4177 |
sizeof(*scsi_cmd), |
3714 |
timeout); |
4178 |
timeout); |
3715 |
} |
4179 |
} |
|
|
4180 |
|
4181 |
void |
4182 |
scsi_read_toc(struct ccb_scsiio *csio, uint32_t retries, |
4183 |
void (*cbfcnp)(struct cam_periph *, union ccb *), |
4184 |
uint8_t tag_action, uint8_t byte1_flags, uint8_t format, |
4185 |
uint8_t track, uint8_t *data_ptr, uint32_t dxfer_len, |
4186 |
int sense_len, int timeout) |
4187 |
{ |
4188 |
struct scsi_read_toc *scsi_cmd; |
4189 |
|
4190 |
scsi_cmd = (struct scsi_read_toc *)&csio->cdb_io.cdb_bytes; |
4191 |
bzero(scsi_cmd, sizeof(*scsi_cmd)); |
4192 |
scsi_cmd->op_code = READ_TOC; |
4193 |
|
4194 |
/* |
4195 |
* The structure is counting from 1, the function counting from 0. |
4196 |
* The spec counts from 0. In MMC-6, there is only one flag, the |
4197 |
* MSF flag. But we put the whole byte in for a bit a future-proofing. |
4198 |
*/ |
4199 |
scsi_cmd->byte2 = byte1_flags; |
4200 |
scsi_cmd->format = format; |
4201 |
scsi_cmd->from_track = track; |
4202 |
scsi_ulto2b(dxfer_len, scsi_cmd->data_len); |
4203 |
|
4204 |
cam_fill_csio(csio, |
4205 |
/* retries */ retries, |
4206 |
/* cbfcnp */ cbfcnp, |
4207 |
/* flags */ CAM_DIR_IN, |
4208 |
/* tag_action */ tag_action, |
4209 |
/* data_ptr */ data_ptr, |
4210 |
/* dxfer_len */ dxfer_len, |
4211 |
/* sense_len */ sense_len, |
4212 |
sizeof(*scsi_cmd), |
4213 |
/* timeout */ timeout); |
4214 |
} |