Browse Source

Plan 9 from Bell Labs 2008-03-11

David du Colombier 16 years ago
parent
commit
5353d592a4

+ 10 - 10
dist/replica/_plan9.db

@@ -181,7 +181,7 @@
 386/bin/cleanname - 775 sys sys 1168402295 58541
 386/bin/cleanname - 775 sys sys 1168402295 58541
 386/bin/clock - 775 sys sys 1197732691 157356
 386/bin/clock - 775 sys sys 1197732691 157356
 386/bin/cmp - 775 sys sys 1157597609 40658
 386/bin/cmp - 775 sys sys 1157597609 40658
-386/bin/col - 775 sys sys 1172029864 64995
+386/bin/col - 775 sys sys 1205206380 63487
 386/bin/colors - 775 sys sys 1197732695 151031
 386/bin/colors - 775 sys sys 1197732695 151031
 386/bin/comm - 775 sys sys 1168402296 61586
 386/bin/comm - 775 sys sys 1168402296 61586
 386/bin/compress - 775 sys sys 1184529900 167036
 386/bin/compress - 775 sys sys 1184529900 167036
@@ -5633,7 +5633,7 @@ rc/bin/stop - 775 sys sys 945617209 110
 rc/bin/tel - 775 sys sys 1161209756 128
 rc/bin/tel - 775 sys sys 1161209756 128
 rc/bin/termrc - 775 sys sys 1179769653 2479
 rc/bin/termrc - 775 sys sys 1179769653 2479
 rc/bin/termrc.local - 775 sys sys 1176500067 425
 rc/bin/termrc.local - 775 sys sys 1176500067 425
-rc/bin/thesaurus - 775 sys sys 1068054167 246
+rc/bin/thesaurus - 775 sys sys 1205183987 422
 rc/bin/tlsclienttunnel - 775 sys sys 1024375633 153
 rc/bin/tlsclienttunnel - 775 sys sys 1024375633 153
 rc/bin/tlssrvtunnel - 775 sys sys 1024375634 175
 rc/bin/tlssrvtunnel - 775 sys sys 1024375634 175
 rc/bin/troff2gif - 775 sys sys 1127410278 164
 rc/bin/troff2gif - 775 sys sys 1127410278 164
@@ -7721,7 +7721,7 @@ sys/man/4/INDEX - 664 sys sys 1196638942 1026
 sys/man/4/INDEX.html - 664 sys sys 1196638942 5147
 sys/man/4/INDEX.html - 664 sys sys 1196638942 5147
 sys/man/4/acme - 664 sys sys 1196638943 10435
 sys/man/4/acme - 664 sys sys 1196638943 10435
 sys/man/4/archfs - 664 sys sys 1196638943 533
 sys/man/4/archfs - 664 sys sys 1196638943 533
-sys/man/4/cdfs - 664 sys sys 1196638943 3638
+sys/man/4/cdfs - 664 sys sys 1205203382 4352
 sys/man/4/cfs - 664 sys sys 1196638943 2136
 sys/man/4/cfs - 664 sys sys 1196638943 2136
 sys/man/4/consolefs - 664 sys sys 1196638943 4389
 sys/man/4/consolefs - 664 sys sys 1196638943 4389
 sys/man/4/cwfs - 664 sys sys 1196638943 6553
 sys/man/4/cwfs - 664 sys sys 1196638943 6553
@@ -8187,7 +8187,7 @@ sys/src/9/pc/uarti8250.c - 664 sys sys 1177676872 13957
 sys/src/9/pc/uartisa.c - 664 sys sys 1127126907 1777
 sys/src/9/pc/uartisa.c - 664 sys sys 1127126907 1777
 sys/src/9/pc/uartpci.c - 664 sys sys 1190235592 4685
 sys/src/9/pc/uartpci.c - 664 sys sys 1190235592 4685
 sys/src/9/pc/usb.h - 664 sys sys 1202865355 4630
 sys/src/9/pc/usb.h - 664 sys sys 1202865355 4630
-sys/src/9/pc/usbohci.c - 664 sys sys 1203981402 49005
+sys/src/9/pc/usbohci.c - 664 sys sys 1205184193 49042
 sys/src/9/pc/usbuhci.c - 664 sys sys 1202252076 31839
 sys/src/9/pc/usbuhci.c - 664 sys sys 1202252076 31839
 sys/src/9/pc/vga.c - 664 sys sys 1131290595 5148
 sys/src/9/pc/vga.c - 664 sys sys 1131290595 5148
 sys/src/9/pc/vga3dfx.c - 664 sys sys 1133218367 3833
 sys/src/9/pc/vga3dfx.c - 664 sys sys 1133218367 3833
@@ -10015,12 +10015,12 @@ sys/src/cmd/cc/scon.c - 664 sys sys 1138463621 8788
 sys/src/cmd/cc/sub.c - 664 sys sys 1143759345 34268
 sys/src/cmd/cc/sub.c - 664 sys sys 1143759345 34268
 sys/src/cmd/cc/y.tab.h - 664 sys sys 1098501521 1680
 sys/src/cmd/cc/y.tab.h - 664 sys sys 1098501521 1680
 sys/src/cmd/cdfs - 20000000775 sys sys 1039727558 0
 sys/src/cmd/cdfs - 20000000775 sys sys 1039727558 0
-sys/src/cmd/cdfs/buf.c - 664 sys sys 964456822 1848
-sys/src/cmd/cdfs/dat.h - 664 sys sys 1204937945 2834
+sys/src/cmd/cdfs/buf.c - 664 sys sys 1205203460 1851
+sys/src/cmd/cdfs/dat.h - 664 sys sys 1205203455 3753
 sys/src/cmd/cdfs/fns.h - 664 sys sys 969542122 297
 sys/src/cmd/cdfs/fns.h - 664 sys sys 969542122 297
-sys/src/cmd/cdfs/main.c - 664 sys sys 1204937969 11147
+sys/src/cmd/cdfs/main.c - 664 sys sys 1205203482 11360
 sys/src/cmd/cdfs/mkfile - 664 sys sys 1204937991 153
 sys/src/cmd/cdfs/mkfile - 664 sys sys 1204937991 153
-sys/src/cmd/cdfs/mmc.c - 664 sys sys 1204938193 20926
+sys/src/cmd/cdfs/mmc.c - 664 sys sys 1205203566 26493
 sys/src/cmd/cec - 20000000775 sys sys 1193683647 0
 sys/src/cmd/cec - 20000000775 sys sys 1193683647 0
 sys/src/cmd/cec/LICENSE - 664 sys sys 1186248056 1554
 sys/src/cmd/cec/LICENSE - 664 sys sys 1186248056 1554
 sys/src/cmd/cec/Protocol - 664 sys sys 1186248056 2881
 sys/src/cmd/cec/Protocol - 664 sys sys 1186248056 2881
@@ -10051,7 +10051,7 @@ sys/src/cmd/chmod.c - 664 sys sys 1079372923 1904
 sys/src/cmd/cleanname.c - 664 sys sys 944960760 715
 sys/src/cmd/cleanname.c - 664 sys sys 944960760 715
 sys/src/cmd/clock.c - 664 sys sys 1014925410 1881
 sys/src/cmd/clock.c - 664 sys sys 1014925410 1881
 sys/src/cmd/cmp.c - 664 sys sys 1157581072 2491
 sys/src/cmd/cmp.c - 664 sys sys 1157581072 2491
-sys/src/cmd/col.c - 664 sys sys 1172005084 3850
+sys/src/cmd/col.c - 664 sys sys 1205188047 3850
 sys/src/cmd/colors.c - 664 sys sys 951763912 3186
 sys/src/cmd/colors.c - 664 sys sys 951763912 3186
 sys/src/cmd/comm.c - 664 sys sys 1093979717 2140
 sys/src/cmd/comm.c - 664 sys sys 1093979717 2140
 sys/src/cmd/compress - 20000000775 sys sys 1157679448 0
 sys/src/cmd/compress - 20000000775 sys sys 1157679448 0
@@ -13614,7 +13614,7 @@ sys/src/cmd/troff/ext.h - 664 sys sys 1116904533 3491
 sys/src/cmd/troff/find - 775 sys sys 944961293 15
 sys/src/cmd/troff/find - 775 sys sys 944961293 15
 sys/src/cmd/troff/fns.h - 664 sys sys 944961293 7329
 sys/src/cmd/troff/fns.h - 664 sys sys 944961293 7329
 sys/src/cmd/troff/hytab.c - 664 sys sys 944961293 7232
 sys/src/cmd/troff/hytab.c - 664 sys sys 944961293 7232
-sys/src/cmd/troff/mkfile - 664 sys sys 1019509075 1034
+sys/src/cmd/troff/mkfile - 664 sys sys 1205186908 1034
 sys/src/cmd/troff/n1.c - 664 sys sys 960145286 20246
 sys/src/cmd/troff/n1.c - 664 sys sys 960145286 20246
 sys/src/cmd/troff/n10.c - 664 sys sys 944961293 11564
 sys/src/cmd/troff/n10.c - 664 sys sys 944961293 11564
 sys/src/cmd/troff/n2.c - 664 sys sys 961261288 5031
 sys/src/cmd/troff/n2.c - 664 sys sys 961261288 5031

+ 10 - 10
dist/replica/plan9.db

@@ -181,7 +181,7 @@
 386/bin/cleanname - 775 sys sys 1168402295 58541
 386/bin/cleanname - 775 sys sys 1168402295 58541
 386/bin/clock - 775 sys sys 1197732691 157356
 386/bin/clock - 775 sys sys 1197732691 157356
 386/bin/cmp - 775 sys sys 1157597609 40658
 386/bin/cmp - 775 sys sys 1157597609 40658
-386/bin/col - 775 sys sys 1172029864 64995
+386/bin/col - 775 sys sys 1205206380 63487
 386/bin/colors - 775 sys sys 1197732695 151031
 386/bin/colors - 775 sys sys 1197732695 151031
 386/bin/comm - 775 sys sys 1168402296 61586
 386/bin/comm - 775 sys sys 1168402296 61586
 386/bin/compress - 775 sys sys 1184529900 167036
 386/bin/compress - 775 sys sys 1184529900 167036
@@ -5633,7 +5633,7 @@ rc/bin/stop - 775 sys sys 945617209 110
 rc/bin/tel - 775 sys sys 1161209756 128
 rc/bin/tel - 775 sys sys 1161209756 128
 rc/bin/termrc - 775 sys sys 1179769653 2479
 rc/bin/termrc - 775 sys sys 1179769653 2479
 rc/bin/termrc.local - 775 sys sys 1176500067 425
 rc/bin/termrc.local - 775 sys sys 1176500067 425
-rc/bin/thesaurus - 775 sys sys 1068054167 246
+rc/bin/thesaurus - 775 sys sys 1205183987 422
 rc/bin/tlsclienttunnel - 775 sys sys 1024375633 153
 rc/bin/tlsclienttunnel - 775 sys sys 1024375633 153
 rc/bin/tlssrvtunnel - 775 sys sys 1024375634 175
 rc/bin/tlssrvtunnel - 775 sys sys 1024375634 175
 rc/bin/troff2gif - 775 sys sys 1127410278 164
 rc/bin/troff2gif - 775 sys sys 1127410278 164
@@ -7721,7 +7721,7 @@ sys/man/4/INDEX - 664 sys sys 1196638942 1026
 sys/man/4/INDEX.html - 664 sys sys 1196638942 5147
 sys/man/4/INDEX.html - 664 sys sys 1196638942 5147
 sys/man/4/acme - 664 sys sys 1196638943 10435
 sys/man/4/acme - 664 sys sys 1196638943 10435
 sys/man/4/archfs - 664 sys sys 1196638943 533
 sys/man/4/archfs - 664 sys sys 1196638943 533
-sys/man/4/cdfs - 664 sys sys 1196638943 3638
+sys/man/4/cdfs - 664 sys sys 1205203382 4352
 sys/man/4/cfs - 664 sys sys 1196638943 2136
 sys/man/4/cfs - 664 sys sys 1196638943 2136
 sys/man/4/consolefs - 664 sys sys 1196638943 4389
 sys/man/4/consolefs - 664 sys sys 1196638943 4389
 sys/man/4/cwfs - 664 sys sys 1196638943 6553
 sys/man/4/cwfs - 664 sys sys 1196638943 6553
@@ -8187,7 +8187,7 @@ sys/src/9/pc/uarti8250.c - 664 sys sys 1177676872 13957
 sys/src/9/pc/uartisa.c - 664 sys sys 1127126907 1777
 sys/src/9/pc/uartisa.c - 664 sys sys 1127126907 1777
 sys/src/9/pc/uartpci.c - 664 sys sys 1190235592 4685
 sys/src/9/pc/uartpci.c - 664 sys sys 1190235592 4685
 sys/src/9/pc/usb.h - 664 sys sys 1202865355 4630
 sys/src/9/pc/usb.h - 664 sys sys 1202865355 4630
-sys/src/9/pc/usbohci.c - 664 sys sys 1203981402 49005
+sys/src/9/pc/usbohci.c - 664 sys sys 1205184193 49042
 sys/src/9/pc/usbuhci.c - 664 sys sys 1202252076 31839
 sys/src/9/pc/usbuhci.c - 664 sys sys 1202252076 31839
 sys/src/9/pc/vga.c - 664 sys sys 1131290595 5148
 sys/src/9/pc/vga.c - 664 sys sys 1131290595 5148
 sys/src/9/pc/vga3dfx.c - 664 sys sys 1133218367 3833
 sys/src/9/pc/vga3dfx.c - 664 sys sys 1133218367 3833
@@ -10015,12 +10015,12 @@ sys/src/cmd/cc/scon.c - 664 sys sys 1138463621 8788
 sys/src/cmd/cc/sub.c - 664 sys sys 1143759345 34268
 sys/src/cmd/cc/sub.c - 664 sys sys 1143759345 34268
 sys/src/cmd/cc/y.tab.h - 664 sys sys 1098501521 1680
 sys/src/cmd/cc/y.tab.h - 664 sys sys 1098501521 1680
 sys/src/cmd/cdfs - 20000000775 sys sys 1039727558 0
 sys/src/cmd/cdfs - 20000000775 sys sys 1039727558 0
-sys/src/cmd/cdfs/buf.c - 664 sys sys 964456822 1848
-sys/src/cmd/cdfs/dat.h - 664 sys sys 1204937945 2834
+sys/src/cmd/cdfs/buf.c - 664 sys sys 1205203460 1851
+sys/src/cmd/cdfs/dat.h - 664 sys sys 1205203455 3753
 sys/src/cmd/cdfs/fns.h - 664 sys sys 969542122 297
 sys/src/cmd/cdfs/fns.h - 664 sys sys 969542122 297
-sys/src/cmd/cdfs/main.c - 664 sys sys 1204937969 11147
+sys/src/cmd/cdfs/main.c - 664 sys sys 1205203482 11360
 sys/src/cmd/cdfs/mkfile - 664 sys sys 1204937991 153
 sys/src/cmd/cdfs/mkfile - 664 sys sys 1204937991 153
-sys/src/cmd/cdfs/mmc.c - 664 sys sys 1204938193 20926
+sys/src/cmd/cdfs/mmc.c - 664 sys sys 1205203566 26493
 sys/src/cmd/cec - 20000000775 sys sys 1193683647 0
 sys/src/cmd/cec - 20000000775 sys sys 1193683647 0
 sys/src/cmd/cec/LICENSE - 664 sys sys 1186248056 1554
 sys/src/cmd/cec/LICENSE - 664 sys sys 1186248056 1554
 sys/src/cmd/cec/Protocol - 664 sys sys 1186248056 2881
 sys/src/cmd/cec/Protocol - 664 sys sys 1186248056 2881
@@ -10051,7 +10051,7 @@ sys/src/cmd/chmod.c - 664 sys sys 1079372923 1904
 sys/src/cmd/cleanname.c - 664 sys sys 944960760 715
 sys/src/cmd/cleanname.c - 664 sys sys 944960760 715
 sys/src/cmd/clock.c - 664 sys sys 1014925410 1881
 sys/src/cmd/clock.c - 664 sys sys 1014925410 1881
 sys/src/cmd/cmp.c - 664 sys sys 1157581072 2491
 sys/src/cmd/cmp.c - 664 sys sys 1157581072 2491
-sys/src/cmd/col.c - 664 sys sys 1172005084 3850
+sys/src/cmd/col.c - 664 sys sys 1205188047 3850
 sys/src/cmd/colors.c - 664 sys sys 951763912 3186
 sys/src/cmd/colors.c - 664 sys sys 951763912 3186
 sys/src/cmd/comm.c - 664 sys sys 1093979717 2140
 sys/src/cmd/comm.c - 664 sys sys 1093979717 2140
 sys/src/cmd/compress - 20000000775 sys sys 1157679448 0
 sys/src/cmd/compress - 20000000775 sys sys 1157679448 0
@@ -13614,7 +13614,7 @@ sys/src/cmd/troff/ext.h - 664 sys sys 1116904533 3491
 sys/src/cmd/troff/find - 775 sys sys 944961293 15
 sys/src/cmd/troff/find - 775 sys sys 944961293 15
 sys/src/cmd/troff/fns.h - 664 sys sys 944961293 7329
 sys/src/cmd/troff/fns.h - 664 sys sys 944961293 7329
 sys/src/cmd/troff/hytab.c - 664 sys sys 944961293 7232
 sys/src/cmd/troff/hytab.c - 664 sys sys 944961293 7232
-sys/src/cmd/troff/mkfile - 664 sys sys 1019509075 1034
+sys/src/cmd/troff/mkfile - 664 sys sys 1205186908 1034
 sys/src/cmd/troff/n1.c - 664 sys sys 960145286 20246
 sys/src/cmd/troff/n1.c - 664 sys sys 960145286 20246
 sys/src/cmd/troff/n10.c - 664 sys sys 944961293 11564
 sys/src/cmd/troff/n10.c - 664 sys sys 944961293 11564
 sys/src/cmd/troff/n2.c - 664 sys sys 961261288 5031
 sys/src/cmd/troff/n2.c - 664 sys sys 961261288 5031

+ 10 - 0
dist/replica/plan9.log

@@ -18728,3 +18728,13 @@
 1205010004 2 c sys/src/9/port/master - 664 sys sys 1205009260 507
 1205010004 2 c sys/src/9/port/master - 664 sys sys 1205009260 507
 1205010004 3 c sys/src/9/port/master.local - 664 sys sys 1205009250 117
 1205010004 3 c sys/src/9/port/master.local - 664 sys sys 1205009250 117
 1205037004 0 c 386/bin/auth/cron - 775 sys sys 1205035791 141213
 1205037004 0 c 386/bin/auth/cron - 775 sys sys 1205035791 141213
+1205184604 0 c rc/bin/thesaurus - 775 sys sys 1205183987 422
+1205184604 1 c sys/src/9/pc/usbohci.c - 664 sys sys 1205184193 49042
+1205188204 0 c sys/src/cmd/col.c - 664 sys sys 1205188047 3850
+1205188204 1 c sys/src/cmd/troff/mkfile - 664 sys sys 1205186908 1034
+1205204404 0 c sys/man/4/cdfs - 664 sys sys 1205203382 4352
+1205204404 1 c sys/src/cmd/cdfs/buf.c - 664 sys sys 1205203460 1851
+1205204404 2 c sys/src/cmd/cdfs/dat.h - 664 sys sys 1205203455 3753
+1205204404 3 c sys/src/cmd/cdfs/main.c - 664 sys sys 1205203482 11360
+1205204404 4 c sys/src/cmd/cdfs/mmc.c - 664 sys sys 1205203566 26493
+1205208004 0 c 386/bin/col - 775 sys sys 1205206380 63487

+ 22 - 13
rc/bin/thesaurus

@@ -2,19 +2,28 @@
 
 
 hget 'http://thesaurus.reference.com/search?q='^$1 |
 hget 'http://thesaurus.reference.com/search?q='^$1 |
 	htmlfmt -l 1000 |
 	htmlfmt -l 1000 |
-	sed -n '
-		1,/^[0-9]+ entries found for/d
-		/ADVERTISEMENT/,$d
-		1,/^$/d
-		s/^Entry://p
-		/^Source:/{
+	sed -n '/^Main Entry:/,/^Source/ {
+		/^Source/ q
+		/^[A-Z].*:/ {
 			N
 			N
-			d
+			s/\n/	/g
 		}
 		}
-		/^[A-Z][a-z]*:/{
-			N
-			s/\n/	/gp
+		p
+	}' | awk -F', ' '{
+		if(length($0)<=70){
+			print
+			next
 		}
 		}
-	'
-
-
+		l = 0
+		for(i = 1; i < NF; i++){
+			printf "%s ", $i
+			l += length($i)+1
+			if(l > 70){
+				printf "\n\t\t"
+				l = 2*ENVIRON["tabstop"]
+			}
+		}
+		if(l>0)
+			printf "\n"
+		next
+	}'

+ 72 - 38
sys/man/4/cdfs

@@ -1,13 +1,12 @@
 .TH CDFS 4
 .TH CDFS 4
 .SH NAME
 .SH NAME
-cdfs, cddb \- CD reader and writer file system
+cdfs, cddb \- optical disc (CD, DVD, BD) reader and writer file system
 .SH SYNOPSIS
 .SH SYNOPSIS
 .B cdfs
 .B cdfs
 [
 [
 .B -d
 .B -d
 .I sddev
 .I sddev
-]
-[
+] [
 .B -m
 .B -m
 .I mtpt
 .I mtpt
 ]
 ]
@@ -17,8 +16,7 @@ cdfs, cddb \- CD reader and writer file system
 .B aux/cddb
 .B aux/cddb
 [
 [
 .B -DTt
 .B -DTt
-]
-[
+] [
 .B -s
 .B -s
 .I server
 .I server
 ]
 ]
@@ -30,21 +28,24 @@ cdfs, cddb \- CD reader and writer file system
 .SH DESCRIPTION
 .SH DESCRIPTION
 .I Cdfs
 .I Cdfs
 serves a one and a half level directory
 serves a one and a half level directory
-mounted at 
+mounted at
 .I mtpt
 .I mtpt
 (default
 (default
 .BR /mnt/cd )
 .BR /mnt/cd )
 that provides access to the tracks
 that provides access to the tracks
-on CDs placed in the CD reader or writer
+on discs placed in the disc reader or writer
 named by
 named by
 .I sddev
 .I sddev
 (default
 (default
 .BR /dev/sdD0 ,
 .BR /dev/sdD0 ,
 see
 see
 .IR sd (3)).
 .IR sd (3)).
+Any MMC-compliant compact disc (CD), DVD,
+or Blu-ray (BD) drive should work.
+On DVD and BD discs, access to data tracks only is implemented.
 .PP
 .PP
 The top level directory contains one file
 The top level directory contains one file
-per CD track.
+per disc track.
 The files are named
 The files are named
 .IR cNNN ,
 .IR cNNN ,
 where
 where
@@ -59,10 +60,9 @@ and
 .I NNN
 .I NNN
 is the track number.
 is the track number.
 .PP
 .PP
-If the device is capable of writing CDs
-and contains a writable CD, the top level
-directory also contains two empty
-directories
+If the device is capable of writing discs
+and contains a writable disc, the top level
+directory also contains two empty directories
 .B wa
 .B wa
 and
 and
 .BR wd .
 .BR wd .
@@ -73,44 +73,53 @@ as new audio or data tracks, regardless of name.
 At any time, any number of tracks
 At any time, any number of tracks
 may be open for reading or a single track
 may be open for reading or a single track
 may be open for writing.
 may be open for writing.
-Writing a CD track is a real-time operation:
-the CD writer must be kept saturated with
+Writing a disc track is a real-time operation:
+the disc writer must be kept saturated with
 new data to avoid buffer underruns.
 new data to avoid buffer underruns.
 To ensure this, copying from a file system
 To ensure this, copying from a file system
-stored on local disk is recommended.
+stored on local disk or memory is recommended.
 .PP
 .PP
-To fixate a CD (close a writable CD by writing
+To fixate a disc (close a recordable disc by writing
 its permanent table of contents), simply
 its permanent table of contents), simply
-remove the 
+remove the
 .B wa
 .B wa
 or
 or
 .B wd
 .B wd
 directory.
 directory.
 The directory removed selects whether
 The directory removed selects whether
-the CD is fixated as an audio or data CD;
+the disc is fixated as an audio or data disc;
 since each track carries its own type information,
 since each track carries its own type information,
 very few readers care which fixation type was used.
 very few readers care which fixation type was used.
+Rewritable discs do not require fixation.
 .PP
 .PP
 The top level directory
 The top level directory
-also contains a 
+also contains a
 .B ctl
 .B ctl
 file, into which control messages
 file, into which control messages
 may be echoed.
 may be echoed.
 The current control messages are:
 The current control messages are:
-.TF "\fLquickblank "
+.TF "\fLquickblan"
+.TP
+.B format
+Format the rewritable disc (\c
+.B -RW
+or
+.BR -RE )
+in the drive
+before initial use.
 .TP
 .TP
 .B blank
 .B blank
-Blank the entire rewritable CD in the drive.
+Blank the entire rewritable disc in the drive.
 .TP
 .TP
 .B quickblank
 .B quickblank
 Blank only the table of contents on the rewritable
 Blank only the table of contents on the rewritable
-CD in the drive.
+disc in the drive.
 .TP
 .TP
 .B eject
 .B eject
-Eject the CD in the drive.
+Eject the disc in the drive.
 .TP
 .TP
 .B ingest
 .B ingest
-Ingest a CD into the drive.
+Ingest a disc into the drive.
 .TP
 .TP
 .B speed \fIkpbs\fR
 .B speed \fIkpbs\fR
 Set the reading and writing speed to use.
 Set the reading and writing speed to use.
@@ -131,10 +140,10 @@ or
 .B write
 .B write
 .BR 8192.
 .BR 8192.
 Note that most drives reset the reading and writing speed
 Note that most drives reset the reading and writing speed
-each time a new CD is inserted.
+each time a new disc is inserted.
 .PD
 .PD
 .PP
 .PP
-Reading the 
+Reading the
 .B ctl
 .B ctl
 file yields information about the drive.
 file yields information about the drive.
 If the drive contains an audio CD, the first line
 If the drive contains an audio CD, the first line
@@ -147,31 +156,40 @@ Subsequent lines contain the current and maximum
 reading and writing speeds.
 reading and writing speeds.
 .PD
 .PD
 .PP
 .PP
-.I Aux/cddb takes 4 optional arguments.
+.I Aux/cddb
+takes 4 optional arguments.
 The
 The
-.B -s server
+.B -s
 option causes
 option causes
 .I aux/cddb
 .I aux/cddb
-to use a different server for the query
+to use a different
+.I server
+for the query
 (default is
 (default is
-.IR freedb.freedb.org ).
+.LR freedb.freedb.org ).
 The
 The
 .B -D
 .B -D
 option causes the raw database response from the server to be dumped
 option causes the raw database response from the server to be dumped
 to standard output.
 to standard output.
 The
 The
-.I -t
+.B -t
 option causes the time of each track to be appended to the normal output.
 option causes the time of each track to be appended to the normal output.
-.I -T
+.B -T
 is like
 is like
-.I -t
+.B -t
 but prints a line with the total time at the end.
 but prints a line with the total time at the end.
 .PD
 .PD
-.PP
-Only MMC-compliant CD readers and writers
-are supported, but it would be easy to add
-support for early CD writers if desired.
 .SH EXAMPLE
 .SH EXAMPLE
+Backup to a BD-RW disc:
+.IP
+.EX
+9fs boot
+cdfs
+tar cbf /mnt/cd/wd/x /n/boot
+.EE
+.br
+.ne 3
+.PP
 Copy the audio tracks from a CD:
 Copy the audio tracks from a CD:
 .IP
 .IP
 .EX
 .EX
@@ -190,10 +208,26 @@ rm /mnt/cd/wa
 .SH SOURCE
 .SH SOURCE
 .B /sys/src/cmd/cdfs
 .B /sys/src/cmd/cdfs
 .SH SEE ALSO
 .SH SEE ALSO
+.TF "\fLhttp://www.t10.org\fP"
+.TP
+.B http://www.t10.org
+optical disc interface standards
+.PP
+.PD
 .IR sd (3),
 .IR sd (3),
 .I 9660srv
 .I 9660srv
 (in
 (in
 .IR dossrv (4)),
 .IR dossrv (4)),
 .IR mk9660 (8)
 .IR mk9660 (8)
 .SH BUGS
 .SH BUGS
-There should be support for DVDs.
+There are too many combinations of optical media, approximately
+the cross-product of these tuples:
+(CD DVD- DVD+ BD),
+(single-layer dual-layer),
+(ROM -R -RW).
+.PP
+Packet (incremental) writing is not yet implemented.
+.PP
+Only MMC-compliant disc readers and writers
+are supported, but it would be easy to add
+support for early CD writers if desired.

+ 4 - 2
sys/src/9/pc/usbohci.c

@@ -1869,6 +1869,9 @@ interrupt(Ureg *, void *arg)
 		case 2:			/* Bitstuff */
 		case 2:			/* Bitstuff */
 			ep->dir[dirin].err = "Bitstuff error";
 			ep->dir[dirin].err = "Bitstuff error";
 			goto error;
 			goto error;
+		case 3:
+			ep->dir[dirin].err = "data toggle mismatch";
+			goto error;
 		case 4:			/* Stall */
 		case 4:			/* Stall */
 			ep->dir[dirin].err = Estalled;
 			ep->dir[dirin].err = Estalled;
 			goto error;
 			goto error;
@@ -1888,8 +1891,7 @@ interrupt(Ureg *, void *arg)
 			wakeup(&ep->dir[dirin].rend);
 			wakeup(&ep->dir[dirin].rend);
 			break;
 			break;
 		default:
 		default:
-			panic("cc %lud unimplemented\n",
-				(ctrl >> TD_CC_SHIFT) & TD_CC_MASK);
+			panic("cc %lud unimplemented\n", cc);
 		}
 		}
 		ep->dir[dirin].queued--;
 		ep->dir[dirin].queued--;
 		/* Clean up blocks used for transfers */
 		/* Clean up blocks used for transfers */

+ 1 - 1
sys/src/cmd/cdfs/buf.c

@@ -41,7 +41,7 @@ bread(Buf *b, void *v, long n, long off)
 		noff = off - off % b->bs;
 		noff = off - off % b->bs;
 		if(vflag)
 		if(vflag)
 			fprint(2, "try refill at %ld\n", noff);
 			fprint(2, "try refill at %ld\n", noff);
-		if((m = b->fn(b, b->data, Nblock, noff/b->bs)) <= 0)
+		if((m = b->fn(b, b->data, b->nblock, noff/b->bs)) <= 0)
 			return m;
 			return m;
 		b->ndata = b->bs * m;
 		b->ndata = b->bs * m;
 		b->off = noff;
 		b->off = noff;

+ 44 - 7
sys/src/cmd/cdfs/dat.h

@@ -1,12 +1,10 @@
 enum {
 enum {
 	Maxtrack	= 200,
 	Maxtrack	= 200,
 	Ntrack		= Maxtrack+1,
 	Ntrack		= Maxtrack+1,
-	BScdrom		= 2048,
+	BScdrom		= 2048,		/* mmc data block size */
 	BScdda		= 2352,
 	BScdda		= 2352,
 	BScdxa		= 2336,
 	BScdxa		= 2336,
 	BSmax		= 2352,
 	BSmax		= 2352,
-	Nalloc		= 12*BScdda,
-	DictBlock	= 1,
 
 
 	/* scsi peripheral device types */
 	/* scsi peripheral device types */
 	TypeDA		= 0,		/* Direct Access (SBC) */
 	TypeDA		= 0,		/* Direct Access (SBC) */
@@ -16,6 +14,13 @@ enum {
 	TypeMO		= 7,		/* rewriteable Magneto-Optical (SBC) */
 	TypeMO		= 7,		/* rewriteable Magneto-Optical (SBC) */
 	TypeMC		= 8,		/* Medium Changer (SMC-2) */
 	TypeMC		= 8,		/* Medium Changer (SMC-2) */
 
 
+	/* MMC-3 device types */
+	Subtypenone	= 0,
+	Subtypecd,
+	Subtypedvd,
+	Subtypebd,
+
+	/* disc or track types */
 	TypeNone	= 0,
 	TypeNone	= 0,
 	TypeAudio,
 	TypeAudio,
 	TypeAwritable,
 	TypeAwritable,
@@ -24,7 +29,29 @@ enum {
 	TypeDisk,
 	TypeDisk,
 	TypeBlank,
 	TypeBlank,
 
 
-	/* Cache control bits in page 8 byte 2 */
+	/* offsets in Pagcapmechsts mode page; see MMC-3 §5.5.10 */
+	Capread		= 2,
+	Capwrite	= 3,
+	Capmisc		= 5,
+
+	/* device capabilities in Pagcapmechsts mode page */
+	Capcdr		= 1<<0,		/* bytes 2 & 3 */
+	Capcdrw		= 1<<1,
+	Captestwr	= 1<<2,
+	Capdvdrom	= 1<<3,
+	Capdvdr		= 1<<4,
+	Capdvdram	= 1<<5,
+	Capcdda		= 1<<0,		/* Capmisc bits */
+	Caprw		= 1<<2,
+
+	/* write types, MMC-6 §7.5.4.9 */
+	Wtpkt	= 0,
+	Wttrackonce,
+	Wtsessonce,
+	Wtraw,
+	Wtlayerjump,
+
+	/* Cache control bits in mode page 8 byte 2 */
 	Ccrcd	= 1<<0,		/* read cache disabled */
 	Ccrcd	= 1<<0,		/* read cache disabled */
 	Ccmf	= 1<<1,		/* multiplication factor */
 	Ccmf	= 1<<1,		/* multiplication factor */
 	Ccwce	= 1<<2,		/* writeback cache enabled */
 	Ccwce	= 1<<2,		/* writeback cache enabled */
@@ -34,10 +61,13 @@ enum {
 	Ccabpf	= 1<<6,		/* abort pre-fetch */
 	Ccabpf	= 1<<6,		/* abort pre-fetch */
 	Ccic	= 1<<7,		/* initiator control */
 	Ccic	= 1<<7,		/* initiator control */
 
 
+	/* drive->cap bits */
 	Cwrite	= 1<<0,
 	Cwrite	= 1<<0,
 	Ccdda	= 1<<1,
 	Ccdda	= 1<<1,
 
 
-	Nblock = 12,
+	CDNblock = 12,		/* chosen for CD */
+	DVDNblock = 16,		/* DVD ECC block is 16 sectors */
+	BDNblock = 32,		/* BD ECC block (`cluster') is 32 sectors */
 };
 };
 
 
 typedef struct Buf Buf;
 typedef struct Buf Buf;
@@ -64,7 +94,6 @@ struct Track
 	Msf	mbeg;
 	Msf	mbeg;
 	Msf	mend;
 	Msf	mend;
 
 
-
 	/* initialized by fs */
 	/* initialized by fs */
 	char	name[32];
 	char	name[32];
 	int	mode;
 	int	mode;
@@ -109,7 +138,9 @@ struct Drive
 	QLock;
 	QLock;
 	Scsi;
 	Scsi;
 
 
+	/* disc characteristics */
 	int	type;
 	int	type;
+	int	subtype;
 	int	nopen;
 	int	nopen;
 	int	firsttrack;
 	int	firsttrack;
 	int	ntrack;
 	int	ntrack;
@@ -117,9 +148,15 @@ struct Drive
 	int	changetime;
 	int	changetime;
 	int	nameok;
 	int	nameok;
 	int	writeok;
 	int	writeok;
+	int	blank;
+	int	blankset;
+	int	recordable;		/* writable by burning? */
+	int	recordableset;
+	int	erasable;		/* rewritable? */
+	int	erasableset;
 
 
 	Track	track[Ntrack];
 	Track	track[Ntrack];
-	ulong	cap;
+	ulong	cap;			/* drive capabilities */
 	uchar	blkbuf[BScdda];
 	uchar	blkbuf[BScdda];
 
 
 	int	maxreadspeed;
 	int	maxreadspeed;

+ 25 - 20
sys/src/cmd/cdfs/main.c

@@ -381,10 +381,10 @@ fsread(Req *r)
 		r->ofcall.count = count;
 		r->ofcall.count = count;
 		respond(r, nil);
 		respond(r, nil);
 	}
 	}
-	return;
 }
 }
 
 
 static char *Ebadmsg = "bad cdfs control message";
 static char *Ebadmsg = "bad cdfs control message";
+
 static char*
 static char*
 writectl(void *v, long count)
 writectl(void *v, long count)
 {
 {
@@ -516,7 +516,12 @@ fsopen(Req *r)
 			return;
 			return;
 		}
 		}
 
 
-		if(omode != OREAD || (o = drive->openrd(drive, fid->qid.path-Qtrack)) == nil) {
+		/*
+		 * allow the open with OWRITE or ORDWR if the
+		 * drive and disc are both capable?
+		 */
+		if(omode != OREAD ||
+		    (o = drive->openrd(drive, fid->qid.path-Qtrack)) == nil) {
 			respond(r, "permission denied");
 			respond(r, "permission denied");
 			return;
 			return;
 		}
 		}
@@ -524,11 +529,10 @@ fsopen(Req *r)
 		o->nref = 1;
 		o->nref = 1;
 		((Aux*)fid->aux)->o = o;
 		((Aux*)fid->aux)->o = o;
 		respond(r, nil);
 		respond(r, nil);
+		break;
 	}
 	}
 }
 }
 
 
-static uchar zero[BScdda];
-
 static void
 static void
 fsdestroyfid(Fid *fid)
 fsdestroyfid(Fid *fid)
 {
 {
@@ -546,6 +550,10 @@ fsdestroyfid(Fid *fid)
 	}
 	}
 }
 }
 
 
+/*
+ * should it be possible on -r or -rw disc to have a mode of 0666,
+ * or do we have to use the wd/x interface?
+ */
 static void
 static void
 checktoc(Drive *drive)
 checktoc(Drive *drive)
 {
 {
@@ -562,6 +570,9 @@ checktoc(Drive *drive)
 			t->mode = 0;
 			t->mode = 0;
 		else
 		else
 			t->mode = 0444;
 			t->mode = 0444;
+		/*
+		 * set mode to 0666 if the drive and disc are both capable?
+		 */
 		sprint(t->name, "?%.3d", i);
 		sprint(t->name, "?%.3d", i);
 		switch(t->type){
 		switch(t->type){
 		case TypeNone:
 		case TypeNone:
@@ -601,14 +612,14 @@ bufwrite(Otrack *t, void *v, long n)
 Srv fs = {
 Srv fs = {
 .attach=	fsattach,
 .attach=	fsattach,
 .destroyfid=	fsdestroyfid,
 .destroyfid=	fsdestroyfid,
-.clone=	fsclone,
-.walk1=	fswalk1,
-.open=	fsopen,
-.read=	fsread,
-.write=	fswrite,
+.clone=		fsclone,
+.walk1=		fswalk1,
+.open=		fsopen,
+.read=		fsread,
+.write=		fswrite,
 .create=	fscreate,
 .create=	fscreate,
 .remove=	fsremove,
 .remove=	fsremove,
-.stat=	fsstat,
+.stat=		fsstat,
 };
 };
 
 
 void
 void
@@ -655,16 +666,10 @@ main(int argc, char **argv)
 	if(dev == nil || mtpt == nil || argc > 0)
 	if(dev == nil || mtpt == nil || argc > 0)
 		usage();
 		usage();
 
 
-	if((s = openscsi(dev)) == nil) {
-		fprint(2, "openscsi '%s': %r\n", dev);
-		exits("openscsi");
-	}
-
-	if((drive = mmcprobe(s)) == nil) {
-		fprint(2, "mmcprobe '%s': %r\n", dev);
-		exits("mmcprobe");
-	}
-
+	if((s = openscsi(dev)) == nil)
+		sysfatal("openscsi '%s': %r", dev);
+	if((drive = mmcprobe(s)) == nil)
+		sysfatal("mmcprobe '%s': %r", dev);
 	checktoc(drive);
 	checktoc(drive);
 
 
 	postmountsrv(&fs, nil, mtpt, MREPL|MCREATE);
 	postmountsrv(&fs, nil, mtpt, MREPL|MCREATE);

+ 274 - 60
sys/src/cmd/cdfs/mmc.c

@@ -37,6 +37,25 @@ struct Mmcaux {
 	long	ntotbk;
 	long	ntotbk;
 };
 };
 
 
+static char *dvdtype[] = {
+	"dvd-rom",
+	"dvd-ram",
+	"dvd-r",
+	"dvd-rw",
+	"hd dvd-rom",
+	"hd dvd-ram",
+	"hd dvd-r",
+	"type 7 (unknown)",
+	"type 8 (unknown)",
+	"dvd+rw",
+	"dvd+r",
+	"type 11 (unknown)",
+	"type 12 (unknown)",
+	"dvd+rw dl",
+	"dvd+r dl",
+	"type 15 (unknown)",
+};
+
 static ulong
 static ulong
 bige(void *p)
 bige(void *p)
 {
 {
@@ -71,8 +90,25 @@ hexdump(void *v, int n)
 		print("\n");
 		print("\n");
 }
 }
 
 
+static void
+initcdb(uchar *cdb, int len, int cmd)
+{
+	memset(cdb, 0, len);
+	cdb[0] = cmd;
+}
+
+static uchar *
+newcdb(int len, int cmd)
+{
+	uchar *cdb;
+
+	cdb = emalloc(len);
+	cdb[0] = cmd;
+	return cdb;
+}
+
 /*
 /*
- * SCSI CCBs (cmd arrays) are 6, 10, 12, 16 or 32 bytes long.
+ * SCSI CDBs (cmd arrays) are 6, 10, 12, 16 or 32 bytes long.
  * The mode sense/select commands implicitly refer to
  * The mode sense/select commands implicitly refer to
  * a mode parameter list, which consists of an 8-byte
  * a mode parameter list, which consists of an 8-byte
  * mode parameter header, followed by zero or more block
  * mode parameter header, followed by zero or more block
@@ -184,7 +220,7 @@ mmcsetpage10(Drive *drive, int page, void *v)
 	p[0] = 0;
 	p[0] = 0;
 	p[1] = len - 2;
 	p[1] = len - 2;
 
 
-	/* set up CCB */
+	/* set up CDB */
 	memset(cmd, 0, sizeof(cmd));
 	memset(cmd, 0, sizeof(cmd));
 	cmd[0] = ScmdMselect10;
 	cmd[0] = ScmdMselect10;
 	cmd[1] = 0x10;			/* format not vendor-specific */
 	cmd[1] = 0x10;			/* format not vendor-specific */
@@ -273,8 +309,7 @@ mmcstatus(Drive *drive)
 {
 {
 	uchar cmd[12];
 	uchar cmd[12];
 
 
-	memset(cmd, 0, sizeof(cmd));
-	cmd[0] = ScmdCDstatus;			/* mechanism status */
+	initcdb(cmd, sizeof cmd, ScmdCDstatus);		/* mechanism status */
 	return scsi(drive, cmd, sizeof(cmd), nil, 0, Sread);
 	return scsi(drive, cmd, sizeof(cmd), nil, 0, Sread);
 }
 }
 
 
@@ -284,7 +319,7 @@ mmcgetspeed(Drive *drive)
 	int n, maxread, curread, maxwrite, curwrite;
 	int n, maxread, curread, maxwrite, curwrite;
 	uchar buf[Pagesz];
 	uchar buf[Pagesz];
 
 
-	n = mmcgetpage(drive, Pagcapmechsts, buf);
+	n = mmcgetpage(drive, Pagcapmechsts, buf);	/* legacy page */
 	maxread = (buf[8]<<8)|buf[9];
 	maxread = (buf[8]<<8)|buf[9];
 	curread = (buf[14]<<8)|buf[15];
 	curread = (buf[14]<<8)|buf[15];
 	maxwrite = (buf[18]<<8)|buf[19];
 	maxwrite = (buf[18]<<8)|buf[19];
@@ -307,7 +342,6 @@ mmcprobe(Scsi *scsi)
 	uchar buf[Pagesz];
 	uchar buf[Pagesz];
 	int cap, n;
 	int cap, n;
 
 
-	/* BUG: confirm mmc better! */
 	if (vflag)
 	if (vflag)
 		print("mmcprobe: inquiry: %s\n", scsi->inquire);
 		print("mmcprobe: inquiry: %s\n", scsi->inquire);
 	drive = emalloc(sizeof(Drive));
 	drive = emalloc(sizeof(Drive));
@@ -316,6 +350,7 @@ mmcprobe(Scsi *scsi)
 	aux = emalloc(sizeof(Mmcaux));
 	aux = emalloc(sizeof(Mmcaux));
 	drive->aux = aux;
 	drive->aux = aux;
 
 
+	/* BUG: confirm mmc better! */
 	/* attempt to read CD capabilities page, but it's now legacy */
 	/* attempt to read CD capabilities page, but it's now legacy */
 	if(mmcgetpage10(drive, Pagcapmechsts, buf) >= 0)
 	if(mmcgetpage10(drive, Pagcapmechsts, buf) >= 0)
 		aux->pagecmdsz = 10;
 		aux->pagecmdsz = 10;
@@ -326,20 +361,24 @@ mmcprobe(Scsi *scsi)
 		free(drive);
 		free(drive);
 		return nil;
 		return nil;
 	}
 	}
-
 	cap = 0;
 	cap = 0;
-	if(buf[3] & 3)		/* 2=cdrw, 1=cdr */
+	if(buf[Capwrite] & (Capcdr|Capcdrw|Capdvdr|Capdvdram) ||
+	    buf[Capmisc] & Caprw)
 		cap |= Cwrite;
 		cap |= Cwrite;
-	if(buf[5] & 1)
-		cap |= Ccdda;
+	if(buf[Capmisc] & Capcdda)	/* CD-DA commands supported? */
+		cap |= Ccdda;		/* not used anywhere else */
 
 
 //	print("read %d max %d\n", biges(buf+14), biges(buf+8));
 //	print("read %d max %d\n", biges(buf+14), biges(buf+8));
 //	print("write %d max %d\n", biges(buf+20), biges(buf+18));
 //	print("write %d max %d\n", biges(buf+20), biges(buf+18));
 
 
 	/* cache optional page 05 (write parameter page) */
 	/* cache optional page 05 (write parameter page) */
-	if((cap & Cwrite) && mmcgetpage(drive, Pagwrparams, aux->page05) >= 0)
+	if(/* (cap & Cwrite) && */
+	    mmcgetpage(drive, Pagwrparams, aux->page05) >= 0) {
 		aux->page05ok = 1;
 		aux->page05ok = 1;
-	else
+		cap |= Cwrite;
+		if (vflag)
+			fprint(2, "mmcprobe: got page 5, assuming writable\n");
+	} else
 		cap &= ~Cwrite;
 		cap &= ~Cwrite;
 
 
 	drive->cap = cap;
 	drive->cap = cap;
@@ -375,7 +414,7 @@ mmctrackinfo(Drive *drive, int t, int i)
 	aux = drive->aux;
 	aux = drive->aux;
 	memset(cmd, 0, sizeof(cmd));
 	memset(cmd, 0, sizeof(cmd));
 	cmd[0] = ScmdRtrackinfo;
 	cmd[0] = ScmdRtrackinfo;
-	cmd[1] = 1;
+	cmd[1] = 1;			/* address below is logical track # */
 	cmd[2] = t>>24;
 	cmd[2] = t>>24;
 	cmd[3] = t>>16;
 	cmd[3] = t>>16;
 	cmd[4] = t>>8;
 	cmd[4] = t>>8;
@@ -385,7 +424,7 @@ mmctrackinfo(Drive *drive, int t, int i)
 	n = scsi(drive, cmd, sizeof(cmd), resp, sizeof(resp), Sread);
 	n = scsi(drive, cmd, sizeof(cmd), resp, sizeof(resp), Sread);
 	if(n < 28) {
 	if(n < 28) {
 		if(vflag)
 		if(vflag)
-			print("trackinfo %d fails n=%d %r\n", t, n);
+			print("trackinfo %d fails n=%d: %r\n", t, n);
 		return -1;
 		return -1;
 	}
 	}
 
 
@@ -410,11 +449,8 @@ mmctrackinfo(Drive *drive, int t, int i)
 		type = TypeNone;
 		type = TypeNone;
 		break;
 		break;
 	case 4:		/* data track, recorded uninterrupted */
 	case 4:		/* data track, recorded uninterrupted */
-		type = TypeData;
-		bs = BScdrom;
-		break;
 	case 5:		/* data track, recorded interrupted */
 	case 5:		/* data track, recorded interrupted */
-		/* treat it as cdrom; probably dvd or bd */
+		/* treat 5 as cdrom; it's probably dvd or bd */
 		type = TypeData;
 		type = TypeData;
 		bs = BScdrom;
 		bs = BScdrom;
 		break;
 		break;
@@ -429,7 +465,7 @@ mmctrackinfo(Drive *drive, int t, int i)
 	drive->track[i].end = beg+size;
 	drive->track[i].end = beg+size;
 	drive->track[i].type = type;
 	drive->track[i].type = type;
 	drive->track[i].bs = bs;
 	drive->track[i].bs = bs;
-	drive->track[i].size = (vlong)(size-2)*bs;	/* -2: skip lead out */
+	drive->track[i].size = (vlong)(size-2) * bs;	/* -2: skip lead out */
 
 
 	if(resp[6] & (1<<6)) {
 	if(resp[6] & (1<<6)) {
 		drive->track[i].type = TypeBlank;
 		drive->track[i].type = TypeBlank;
@@ -438,10 +474,10 @@ mmctrackinfo(Drive *drive, int t, int i)
 
 
 	if(t == 0xFF)
 	if(t == 0xFF)
 		aux->mmcnwa = bige(&resp[12]);
 		aux->mmcnwa = bige(&resp[12]);
-
 	return 0;
 	return 0;
 }
 }
 
 
+/* this may fail for blank media */
 static int
 static int
 mmcreadtoc(Drive *drive, int type, int track, void *data, int nbytes)
 mmcreadtoc(Drive *drive, int type, int track, void *data, int nbytes)
 {
 {
@@ -488,6 +524,108 @@ rdmsf(uchar *p)
 	return msf;
 	return msf;
 }
 }
 
 
+static int
+getdiscinfo(Drive *drive, uchar resp[], int resplen)
+{
+	int n;
+
+	n = mmcreaddiscinfo(drive, resp, resplen);
+	if(n < 3)
+		return n;
+	if (vflag)
+		fprint(2, "read disc info succeeded\n");
+	assert((resp[2] & 0340) == 0);			/* data type 0 */
+	drive->erasable = ((resp[2] & 0x10) != 0);	/* -RW? */
+	drive->erasableset = 1;
+	return n;
+}
+
+static int
+getdvdstruct(Drive *drive)
+{
+	int n;
+	uchar cmd[12], resp[Pagesz];
+
+	initcdb(cmd, sizeof cmd, ScmdReadDVD); /* actually, read disc structure */
+	cmd[1] = 0;			/* media type: dvd */
+	cmd[7] = 0;			/* format code: physical format */
+	cmd[8] = sizeof resp >> 8;	/* allocation length */
+	cmd[9] = sizeof resp;
+	n = scsi(drive, cmd, sizeof(cmd), resp, sizeof resp, Sread);
+	if (n < 7)
+		return -1;
+	/*
+	 * resp[0..1] is resp length
+	 * (resp[4] & 0xf0) >> 4 is dvd type (disk category), MMC-6 §6.22.3.2.1
+	 */
+	if (vflag)
+		fprint(2, "dvd type is %s\n", dvdtype[(resp[4] & 0xf0) >> 4]);
+	/* write parameters mode page may suffice to compute writeok for dvd */
+	drive->erasable = drive->recordable = 0;
+	switch (resp[6] & 0xf) {		/* layer type */
+	case 0:					/* embossed data */
+		drive->blank = 0;
+		drive->blankset = 1;
+		break;
+	case 1:					/* recordable */
+		drive->recordable = 1;
+		break;
+	case 2:					/* rewritable */
+		drive->erasable = 1;
+		break;
+	default:
+		fprint(2, "%s: unknown dvd layer type %d\n",
+			argv0, resp[6] & 0xf);
+		return -1;
+	}
+	drive->erasableset = drive->recordableset = 1;
+	drive->subtype = Subtypedvd;
+	return 0;
+}
+
+static int
+getbdstruct(Drive *drive)
+{
+	int n;
+	uchar cmd[12], resp[4100];
+
+	initcdb(cmd, sizeof cmd, ScmdReadDVD); /* actually, read disc structure */
+	cmd[1] = 1;			/* media type: bd */
+	cmd[7] = 0;			/* format code: disc info */
+	cmd[8] = sizeof resp >> 8;	/* allocation length */
+	cmd[9] = sizeof resp;
+	n = scsi(drive, cmd, sizeof(cmd), resp, sizeof resp, Sread);
+	if (n < 4+8+3)
+		return -1;
+	if (vflag)
+		fprint(2, "read disc structure (bd) succeeded\n");
+	/*
+	 * resp[0..1] is resp length
+	 * resp[4+8..4+8+2] is bd type (disc type identifier):
+	 * BDO|BDW|BDR, MMC-6 §6.22.3.3.1
+	 */
+	assert(resp[4+8] == 'B' && resp[4+8+1] == 'D');
+	drive->erasable = drive->recordable = 0;
+	switch (resp[4+8+2]) {
+	case 'O':
+		drive->blank = 0;
+		drive->blankset = 1;
+		break;
+	case 'W':				/* recordable */
+		drive->recordable = 1;
+		break;
+	case 'R':				/* rewritable */
+		drive->erasable = 1;
+		break;
+	default:
+		fprint(2, "%s: unknown bd type BD%c\n", argv0, resp[4+8+2]);
+		return -1;
+	}
+	drive->erasableset = drive->recordableset = 1;
+	drive->subtype = Subtypebd;
+	return 0;
+}
+
 static int
 static int
 mmcgettoc(Drive *drive)
 mmcgettoc(Drive *drive)
 {
 {
@@ -515,13 +653,18 @@ mmcgettoc(Drive *drive)
 	drive->nameok = 0;
 	drive->nameok = 0;
 	drive->nchange = drive->Scsi.nchange;
 	drive->nchange = drive->Scsi.nchange;
 	drive->changetime = drive->Scsi.changetime;
 	drive->changetime = drive->Scsi.changetime;
-	drive->writeok = 0;
+	drive->writeok = drive->erasable = drive->recordable = drive->blank = 0;
+	drive->erasableset = drive->recordableset = drive->blankset = 0;
 
 
 	for(i=0; i<nelem(drive->track); i++){
 	for(i=0; i<nelem(drive->track); i++){
 		memset(&drive->track[i].mbeg, 0, sizeof(Msf));
 		memset(&drive->track[i].mbeg, 0, sizeof(Msf));
 		memset(&drive->track[i].mend, 0, sizeof(Msf));
 		memset(&drive->track[i].mend, 0, sizeof(Msf));
 	}
 	}
 
 
+	/*
+	 * TODO: set read ahead, MMC-6 §6.37, seems to control caching.
+	 */
+
 	/*
 	/*
 	 * find number of tracks
 	 * find number of tracks
 	 */
 	 */
@@ -530,29 +673,52 @@ mmcgettoc(Drive *drive)
 		 * on a blank disc in a cd-rw, use readdiscinfo
 		 * on a blank disc in a cd-rw, use readdiscinfo
 		 * to find the track info.
 		 * to find the track info.
 		 */
 		 */
-		if(mmcreaddiscinfo(drive, resp, sizeof(resp)) < 0)
+		if(getdiscinfo(drive, resp, sizeof(resp)) < 7)
 			return -1;
 			return -1;
+		assert((resp[2] & 0340) == 0);	/* data type 0 */
+		drive->erasable = ((resp[2] & 0x10) != 0);
+		drive->erasableset = 1;
 		if(resp[4] != 1)
 		if(resp[4] != 1)
 			print("multi-session disc %d\n", resp[4]);
 			print("multi-session disc %d\n", resp[4]);
 		first = resp[3];
 		first = resp[3];
 		last = resp[6];
 		last = resp[6];
 		if(vflag)
 		if(vflag)
 			print("blank disc %d %d\n", first, last);
 			print("blank disc %d %d\n", first, last);
-		drive->writeok = 1;
+		drive->writeok = drive->blank = drive->blankset = 1;
 	} else {
 	} else {
 		first = resp[2];
 		first = resp[2];
 		last = resp[3];
 		last = resp[3];
 
 
 		if(n >= 4+8*(last-first+2)) {
 		if(n >= 4+8*(last-first+2)) {
-			for(i=0; i<=last-first+1; i++)	/* <=: track[last-first+1] = end */
+			/* <=: track[last-first+1] = end */
+			for(i=0; i<=last-first+1; i++)
 				drive->track[i].mbeg = rdmsf(resp+4+i*8+5);
 				drive->track[i].mbeg = rdmsf(resp+4+i*8+5);
 			for(i=0; i<last-first+1; i++)
 			for(i=0; i<last-first+1; i++)
 				drive->track[i].mend = drive->track[i+1].mbeg;
 				drive->track[i].mend = drive->track[i+1].mbeg;
 		}
 		}
 	}
 	}
 
 
-	if(vflag)
+	getdvdstruct(drive);
+	getbdstruct(drive);
+
+	if (drive->subtype == Subtypenone)
+		drive->subtype = Subtypecd;	/* by default */
+	if (drive->recordable || drive->erasable)
+		drive->writeok = 1;
+//	if (drive->subtype == Subtypecd && otrack->buf->ndata == 0)
+//		otrack->buf->nblock = CDNblock;
+
+	if (vflag) {
+		fprint(2, "writeok %d", drive->writeok);
+		if (drive->blankset)
+			fprint(2, " blank %d", drive->blank);
+		if (drive->recordableset)
+			fprint(2, " recordable %d", drive->recordable);
+		if (drive->erasableset)
+			fprint(2, " erasable %d", drive->erasable);
+		fprint(2, "\n");
 		print("first %d last %d\n", first, last);
 		print("first %d last %d\n", first, last);
+	}
 
 
 	if(first == 0 && last == 0)
 	if(first == 0 && last == 0)
 		first = 1;
 		first = 1;
@@ -589,7 +755,7 @@ mmcgettoc(Drive *drive)
 			}
 			}
 		}
 		}
 
 
-		if((long)drive->track[0].beg < 0)	/* i've seen negative track 0's */
+		if((long)drive->track[0].beg < 0) /* i've seen negative track 0's */
 			drive->track[0].beg = 0;
 			drive->track[0].beg = 0;
 
 
 		tot = 0;
 		tot = 0;
@@ -607,7 +773,8 @@ mmcgettoc(Drive *drive)
 				t->beg = 0;
 				t->beg = 0;
 				t->end = 0;
 				t->end = 0;
 			}
 			}
-			t->size = (t->end - t->beg - 2) * (vlong)t->bs;	/* -2: skip lead out */
+			/* -2: skip lead out */
+			t->size = (t->end - t->beg - 2) * (vlong)t->bs;
 		}
 		}
 	}
 	}
 
 
@@ -630,35 +797,53 @@ mmcsetbs(Drive *drive, int bs)
 		return 0;			/* harmless; assume 2k */
 		return 0;			/* harmless; assume 2k */
 
 
 	p = aux->page05;
 	p = aux->page05;
-	p[2] = 0x01;				/* track-at-once */
+	/*
+	 * establish defaults.
+	 * p[2] & 0xf is write type.
+	 * p[3] & 0xf is track mode.
+	 * p[4] & 0xf is data-block type.
+	 * p[8] is session format.
+	 */
+	p[2] = Wttrackonce;
 //	if(xflag)
 //	if(xflag)
-//		p[2] |= 0x10;			/* test-write */
-
-	switch(bs){
-	case BScdrom:
-		p[3] = (p[3] & ~0x07)|0x04;	/* data track, uninterrupted */
-		p[4] = 0x08;			/* mode 1 CD-ROM */
-		p[8] = 0;			/* session format CD-DA or CD-ROM */
-		break;
-
-	case BScdda:
-		p[3] = (p[3] & ~0x07)|0x00;	/* 2 audio channels without pre-emphasis */
-		p[4] = 0x00;			/* raw data */
-		p[8] = 0;			/* session format CD-DA or CD-ROM */
+//		p[2] |= 0x10;		/* test-write */
+	p[3] &= ~0xf;
+	p[3] |= 5;			/* dvd default track mode */
+	p[4] = 0x08;			/* mode 1 CD-ROM: 2K user data */
+	p[8] = 0;			/* session format, CD-DA or -ROM (data) */
+	switch(drive->subtype) {
+	case Subtypecd:
+		p[3] = (p[3] & ~0x07)|0x04; /* data track, uninterrupted */
+		switch(bs){
+		case BScdrom:
+			break;
+		case BScdda:
+			/* 2 audio channels without pre-emphasis */
+			p[3] = (p[3] & ~0x07)|0x00;
+			p[4] = 0x00;	/* raw data */
+			break;
+		case BScdxa:
+			p[4] = 0x09;	/* mode 2: 2336 bytes user data */
+			p[8] = 0x20;	/* session format CD-ROM XA */
+			break;
+		default:
+			fprint(2, "%s: unknown CD type; bs %d\n", argv0, bs);
+			assert(0);
+		}
 		break;
 		break;
-
-	case BScdxa:
-		p[3] = (p[3] & ~0x07)|0x04;	/* data track, uninterrupted */
-		p[4] = 0x09;			/* mode 2 */
-		p[8] = 0x20;			/* session format CD-ROM XA */
+	case Subtypedvd:
+	case Subtypebd:
 		break;
 		break;
-
 	default:
 	default:
-		assert(0);
+		fprint(2, "%s: unknown disc sub-type %d\n",
+			argv0, drive->subtype);
+		break;
 	}
 	}
-
-	if(mmcsetpage(drive, Pagwrparams, p) < 0)
+	if(mmcsetpage(drive, Pagwrparams, p) < 0) {
+		if (vflag)
+			fprint(2, "mmcsetbs: could NOT set write parameters page\n");
 		return -1;
 		return -1;
+	}
 	return 0;
 	return 0;
 }
 }
 
 
@@ -774,7 +959,7 @@ mmcopenrd(Drive *drive, int trackno)
 	o->track = &drive->track[trackno];
 	o->track = &drive->track[trackno];
 	o->nchange = drive->nchange;
 	o->nchange = drive->nchange;
 	o->omode = OREAD;
 	o->omode = OREAD;
-	o->buf = bopen(mmcread, OREAD, o->track->bs, Nblock);
+	o->buf = bopen(mmcread, OREAD, o->track->bs, BDNblock);
 	o->buf->otrack = o;
 	o->buf->otrack = o;
 
 
 	aux->nropen++;
 	aux->nropen++;
@@ -782,6 +967,29 @@ mmcopenrd(Drive *drive, int trackno)
 	return o;
 	return o;
 }
 }
 
 
+static int
+format(Drive *drive)
+{
+	uchar *fmtdesc;
+	uchar cmd[6], parms[4+8];
+
+	initcdb(cmd, sizeof cmd, ScmdFormat);	/* format unit */
+	cmd[1] = 0x10 | 1;		/* format data, mmc format code */
+
+	memset(parms, 0, sizeof parms);
+	parms[1] = 2;			/* immediate return; don't wait */
+	parms[3] = 8;			/* format descriptor length */
+
+	fmtdesc = parms + 4;
+	PUTBELONG(fmtdesc, ~0ul);
+	fmtdesc[4] = 0;			/* full format */
+	PUTBE24(fmtdesc + 5, BScdrom);
+
+	if(vflag)
+		print("%lld ns: format\n", nsec());
+	return scsi(drive, cmd, sizeof(cmd), parms, sizeof parms, Swrite);
+}
+
 static long
 static long
 mmcxwrite(Otrack *o, void *v, long nblk)
 mmcxwrite(Otrack *o, void *v, long nblk)
 {
 {
@@ -793,6 +1001,7 @@ mmcxwrite(Otrack *o, void *v, long nblk)
 	aux = o->drive->aux;
 	aux = o->drive->aux;
 	aux->ntotby += nblk*o->track->bs;
 	aux->ntotby += nblk*o->track->bs;
 	aux->ntotbk += nblk;
 	aux->ntotbk += nblk;
+
 	memset(cmd, 0, sizeof(cmd));
 	memset(cmd, 0, sizeof(cmd));
 	cmd[0] = ScmdExtwrite;		/* write (10) */
 	cmd[0] = ScmdExtwrite;		/* write (10) */
 	cmd[2] = aux->mmcnwa>>24;
 	cmd[2] = aux->mmcnwa>>24;
@@ -802,7 +1011,7 @@ mmcxwrite(Otrack *o, void *v, long nblk)
 	cmd[7] = nblk>>8;
 	cmd[7] = nblk>>8;
 	cmd[8] = nblk>>0;
 	cmd[8] = nblk>>0;
 	if(vflag)
 	if(vflag)
-		print("%lld: write %ld at 0x%lux\n", nsec(), nblk, aux->mmcnwa);
+		print("%lld ns: write %ld at 0x%lux\n", nsec(), nblk, aux->mmcnwa);
 	aux->mmcnwa += nblk;
 	aux->mmcnwa += nblk;
 	return scsi(o->drive, cmd, sizeof(cmd), v, nblk*o->track->bs, Swrite);
 	return scsi(o->drive, cmd, sizeof(cmd), v, nblk*o->track->bs, Swrite);
 }
 }
@@ -840,17 +1049,18 @@ mmccreate(Drive *drive, int type)
 		return nil;
 		return nil;
 	}
 	}
 
 
+/* comment out the returns for now; it should be no big deal - geoff */
 	if(mmctrackinfo(drive, 0xFF, Maxtrack)) {	/* the invisible track */
 	if(mmctrackinfo(drive, 0xFF, Maxtrack)) {	/* the invisible track */
 		werrstr("CD not writable");
 		werrstr("CD not writable");
-		return nil;
+//		return nil;
 	}
 	}
 	if(mmcsetbs(drive, bs) < 0) {
 	if(mmcsetbs(drive, bs) < 0) {
 		werrstr("cannot set bs mode");
 		werrstr("cannot set bs mode");
-		return nil;
+//		return nil;
 	}
 	}
 	if(mmctrackinfo(drive, 0xFF, Maxtrack)) {	/* the invisible track */
 	if(mmctrackinfo(drive, 0xFF, Maxtrack)) {	/* the invisible track */
 		werrstr("CD not writable 2");
 		werrstr("CD not writable 2");
-		return nil;
+//		return nil;
 	}
 	}
 
 
 	aux->ntotby = 0;
 	aux->ntotby = 0;
@@ -869,7 +1079,7 @@ mmccreate(Drive *drive, int type)
 	o->nchange = drive->nchange;
 	o->nchange = drive->nchange;
 	o->omode = OWRITE;
 	o->omode = OWRITE;
 	o->track = t;
 	o->track = t;
-	o->buf = bopen(mmcwrite, OWRITE, bs, Nblock);
+	o->buf = bopen(mmcwrite, OWRITE, bs, BDNblock);
 	o->buf->otrack = o;
 	o->buf->otrack = o;
 
 
 	aux->nwopen++;
 	aux->nwopen++;
@@ -924,8 +1134,8 @@ mmcxclose(Drive *drive, int ts, int trackno)
 	 * ts: 1 == track, 2 == session
 	 * ts: 1 == track, 2 == session
 	 */
 	 */
 	memset(cmd, 0, sizeof(cmd));
 	memset(cmd, 0, sizeof(cmd));
-	cmd[0] = ScmdClosetracksess;
-	cmd[2] = ts;
+	cmd[0] = ScmdClosetracksess;		/* fixate */
+	cmd[2] = ts;				/* close function */
 	if(ts == 1)
 	if(ts == 1)
 		cmd[5] = trackno;
 		cmd[5] = trackno;
 	return scsi(drive, cmd, sizeof(cmd), cmd, 0, Snone);
 	return scsi(drive, cmd, sizeof(cmd), cmd, 0, Snone);
@@ -944,9 +1154,10 @@ mmcfixate(Drive *drive)
 
 
 	drive->nchange = -1;		/* force reread toc */
 	drive->nchange = -1;		/* force reread toc */
 
 
-	/* TODO: page 5 is legacy and now read-only */
+	/* page 5 is legacy and now read-only */
 	aux = drive->aux;
 	aux = drive->aux;
 	p = aux->page05;
 	p = aux->page05;
+	/* zero multi-session field: next session not allowed */
 	p[3] &= ~0xC0;
 	p[3] &= ~0xC0;
 	if(mmcsetpage(drive, Pagwrparams, p) < 0)
 	if(mmcsetpage(drive, Pagwrparams, p) < 0)
 		return -1;
 		return -1;
@@ -963,9 +1174,10 @@ mmcsession(Drive *drive)
 
 
 	drive->nchange = -1;	/* force reread toc */
 	drive->nchange = -1;	/* force reread toc */
 
 
-	/* TODO: page 5 is legacy and now read-only */
+	/* page 5 is legacy and now read-only */
 	aux = drive->aux;
 	aux = drive->aux;
 	p = aux->page05;
 	p = aux->page05;
+	/* zero multi-session field: next session not allowed */
 	p[3] &= ~0xC0;
 	p[3] &= ~0xC0;
 	if(mmcsetpage(drive, Pagwrparams, p) < 0)
 	if(mmcsetpage(drive, Pagwrparams, p) < 0)
 		return -1;
 		return -1;
@@ -1014,6 +1226,8 @@ mmcctl(Drive *drive, int argc, char **argv)
 	if(argc < 1)
 	if(argc < 1)
 		return nil;
 		return nil;
 
 
+	if(strcmp(argv[0], "format") == 0)
+		return e(format(drive));
 	if(strcmp(argv[0], "blank") == 0)
 	if(strcmp(argv[0], "blank") == 0)
 		return e(mmcblank(drive, 0));
 		return e(mmcblank(drive, 0));
 	if(strcmp(argv[0], "quickblank") == 0)
 	if(strcmp(argv[0], "quickblank") == 0)

+ 8 - 8
sys/src/cmd/col.c

@@ -177,7 +177,7 @@ outc(Rune c)
 	while (*line == '\b')
 	while (*line == '\b')
 		line += 2;
 		line += 2;
 	if (bflag || *line == '\0' || *line == ' ')
 	if (bflag || *line == '\0' || *line == ' ')
-		*line = c;
+		cp += runetochar(line, &c) - 1;
 	else {
 	else {
 		char c1, c2, c3;
 		char c1, c2, c3;
 
 
@@ -232,17 +232,17 @@ emit(char *s, int lineno)
 
 
 	if (*s) {
 	if (*s) {
 		while (cline < lineno - 1) {
 		while (cline < lineno - 1) {
-			Bputrune(&bout, '\n');
+			Bputc(&bout, '\n');
 			pcp = 0;
 			pcp = 0;
 			cline += 2;
 			cline += 2;
 		}
 		}
 		if (cline != lineno) {
 		if (cline != lineno) {
-			Bputrune(&bout, ESC);
-			Bputrune(&bout, '9');
+			Bputc(&bout, ESC);
+			Bputc(&bout, '9');
 			cline++;
 			cline++;
 		}
 		}
 		if (pcp)
 		if (pcp)
-			Bputrune(&bout, '\r');
+			Bputc(&bout, '\r');
 		pcp = 0;
 		pcp = 0;
 		p = s;
 		p = s;
 		while (*p) {
 		while (*p) {
@@ -250,15 +250,15 @@ emit(char *s, int lineno)
 			while (*p++ == ' ')
 			while (*p++ == ' ')
 				if ((++ncp & 7) == 0 && !xflag) {
 				if ((++ncp & 7) == 0 && !xflag) {
 					pcp = ncp;
 					pcp = ncp;
-					Bputrune(&bout, '\t');
+					Bputc(&bout, '\t');
 				}
 				}
 			if (!*--p)
 			if (!*--p)
 				break;
 				break;
 			while (pcp < ncp) {
 			while (pcp < ncp) {
-				Bputrune(&bout, ' ');
+				Bputc(&bout, ' ');
 				pcp++;
 				pcp++;
 			}
 			}
-			Bputrune(&bout, *p);
+			Bputc(&bout, *p);
 			if (*p++ == '\b')
 			if (*p++ == '\b')
 				pcp--;
 				pcp--;
 			else
 			else

+ 1 - 1
sys/src/cmd/troff/mkfile

@@ -51,7 +51,7 @@ n1.$O:	n1.c $HFILES
 	$CC $CFLAGS -DFONTDIR'='$FONTDIR -DNTERMDIR'='$NTERMDIR -DTEXHYPHENS'='$TEXHYPHENS -DALTHYPHENS'='$TEXHYPHENS -DDWBHOME'='$DWBHOME n1.c
 	$CC $CFLAGS -DFONTDIR'='$FONTDIR -DNTERMDIR'='$NTERMDIR -DTEXHYPHENS'='$TEXHYPHENS -DALTHYPHENS'='$TEXHYPHENS -DDWBHOME'='$DWBHOME n1.c
 
 
 n10.$O:	n10.c $HFILES
 n10.$O:	n10.c $HFILES
-	$CC $CFLAGS -DTDEVNAME'='$NDEVNAME n10.c
+	$CC $CFLAGS -DNDEVNAME'='$NDEVNAME n10.c
 
 
 n8.$O:	n8.c $HFILES
 n8.$O:	n8.c $HFILES
 	$CC $CFLAGS -DTEXHYPHENS'='$TEXHYPHENS n8.c
 	$CC $CFLAGS -DTEXHYPHENS'='$TEXHYPHENS n8.c