這一章主要是在討論 FreeBSD 上有關 serial 通訊的問題。有關 PPP 以及 SLIP 的問題是放在 Chapter 9 這一節。
當 FreeBSD 開機的時候,它會根據您在 kernel 中的設定來偵測您的 serial port。您可以在這些訊息出現的時候檢查,也可以在系統開機之後用 下面的指令來觀察:
dmesg | grep sio
這裡有一些輸出的範例:
sio0 at 0x3f8-0x3ff irq 4 on isa
sio0: type 16550A
sio1 at 0x2f8-0x2ff irq 3 on isa
sio1: type 16550A
這代表您有兩個 serial port。第一個 port 佔用 irq 4,port address 是 0x3f8 ,而且用的是 16550A 型的 UART 晶片。第二個 port 用的是同 型的晶片,不過它佔用的是 irq 3 ,它的 port address 在 0x2f8 。 內接式 modem 卡會被辨識成是 serial port -- 唯一的差別就是該 port 上 總是接上 modem 而已。
GENERIC kernel 支援兩個 serial port ,它們的設定值就如同上面的 範例一樣。如果您系統上的設定不一樣,或者您另外接了內接式 modem 卡, 或是您系統的實際 serial port 數比您在 kernel 設定中的還要多的話,您 只要重新建立 kernel 就好了。詳情請看 如何建立 kernel。
第三個 serial port,sio2 (就是 DOS 下的 COM3) ,以 dial-out 裝置來看是位於 /dev/cuaa2 ,而以 dial-in 裝置來看則是位於 /dev/ttyd2 。這兩個裝置有什麼不同 呢?
您在 dial-in 時使用的是 ttydX 。當您用 block 模式開啟 /dev/ttydX 時,會有一隻 process 在對應的 cuaaX 上等它 變成 inactive ,然後一直等到 carrier detect line 變成 active 為止。 當您開啟 cuaaX 裝置時,它會去確定目前 ttydX 裝置是不是正 在使用 serial port。如果它可以用的話,它就會把 serial port 從 ttydX 裝置手中搶過來。同樣的,cuaXX 裝置不會去管 carrier detect。有了這樣的設計,再加上一台會自動回應的 modem,您就可以令同 一台 modem 可以被遠端使用者拿來登入,您自己也可以拿來 dialout,系統 會自動檢查是否有衝突的現象。
同樣的,在 kernel 設定那一節有提到有關設定 kernel 的資訊。要設定一 張 serial 多埠卡,您必需在您的 kernel 設定檔中為每一個 serial port 都設一行 sio 的設定。但是您只能在它們之中選一個來設定 irq 以及 vector 。卡上的所有 port 會共享同一個 irq 。一般來說我們都把它設在最 後一個 serial port 上。不要忘了指定 COM_MULTIPORT 這個 option 。
下面是一個把 AST 4-port 卡 設在 irq 7 的例子:
options "COM_MULTIPORT"
device sio4 at isa? port 0x2a0 tty flags 0x781
device sio5 at isa? port 0x2a8 tty flags 0x781
device sio6 at isa? port 0x2b0 tty flags 0x781
device sio7 at isa? port 0x2b8 tty flags 0x781 irq 7 vector siointr
這裡的 flags 設定是指 master port 的 minor number 是 7 (0x700),在偵測時做檢查 (0x080),以及所有的 port 共享一個 irq (0x001) 。
通常您會想為您的應用程式開啟 ttydX (或是 cuaaX) 裝置。當 一個 process 開啟裝置以後,它會有一組預設的終端機 I/O 設定。您可以用 下面這個指令來觀察這些設定
stty -a -f /dev/ttyd1
當您改變了某個裝置的設定後,這些設定會一直作用,直到這個裝置被關閉 了為止。當它被重開啟後,又回到原先的預設值了。如果想要改變預設值,您 可以開啟並修改 ``初始狀態'' 裝置的設定。舉例來說,如果您想改變 ttyd5 的預設值,把 CLOCAL 模式打開,8 bits,並且使用 XON/XOFF 流量控制,您可以這樣做:
stty -f /dev/ttyid5 clocal cs8 ixon ixoff
您可以在 /etc/rc.serial 裡做這樣的設定。現在每一個開啟 ttyd5 的應用程式都會預設使用這些設定了。您依然可以用同樣的方法 去改變這些設定。
您也可以藉由設定 ``鎖定狀態'' 裝置來防止其他應用程式去更動這些設定 。舉例來說,想要把 ttyd5 的速度鎖定在 57600 bps,您要這樣做
stty -f /dev/ttyld5 57600
這樣一來,每一個開啟 ttyd5 的應用程式都只能使用 57600 bps 的速 度了。
當然,您必需確定您的初始狀態以及鎖定狀態的裝置只能被 root 寫入 。MAKEDEV 這個 script 並 不會 在建立這些裝置時自動幫您設 定好。
您是不是想當 ISP?首先,您要有一部以上可以自動接聽的 modem。您的 modem 必須要有 carrier-detect 的功能。它也要能夠在 data terminal ready (DTR) 由開轉為關時重新設定自己。它或許也要能夠使用 RTS/CTS 流量控制或是不做任何流量控制。最後,它必須能夠在電 腦和它自己的傳輸中使用定速,但是在它和遠端 modem 的連線方面則要有協 商傳輸速度的能力。
對 Hayes 指令集相容 modem 來說,下面的指令會把上一段所講的全部設好 並存在非揮發性記憶體中:
AT &C1 &D3 &K3 &Q6 S0=1 &W
看看下面的 傳送 AT 指令集 這一節可以得 更多有關如何不利用 MS-DOS 終端程式來做這些設定的資料。
接下來,在 /etc/ttys 為您的 modem 做設定。列在這個檔案中的是所有系統會 待 login 的 ports 。像下面這樣加入一行:
ttyd1 "/usr/libexec/getty std.57600" dialup on insecure
這一行指令第二個 serial port (/dev/ttyd1) 是一個以 57600 bps 速度在傳輸的 modem,並且不做同位檢查 ( std.57600 是在 /etc/gettytab 檔裡指定的)。 這個 port 的終端機型態是 ``dialup''。這個 port 設成 ``on'' 而且是 ``insecure'' 的 --- 意思是 root 不能從這裡連線進來。您必需為每個 dialin port 都做類似 ttydX 的設定。
通常我們會用 ``dialup'' 來做為終端機型態。如果使用者登入時的啟始型 態是 dialup 的話,很多使用者都會在他們的 .profile 或是 .login 檔中設 定他們真正的終端機型態。上面的例子中我們舉的是 insecure 的例子。如果 您想要在這個 port 變成 root 的話,您必須用一般使用者的身份登入,然後 ``su'' 成 root 。如果您用的是 ``secure'' 的話,則 root 可以直接登 入。
在對 /etc/ttys 做過修改之後,您必須送一個 hangup 或是 HUP 的 signal 給 init process:
kill -HUP 1
這樣會強迫 init process 去重讀 /etc/ttys 。 然後 init process 就會在所有的 ``on'' port 上重新啟動 getty process 。您可以用下列指令來檢查您的 port 是不是可以 login 了
ps -ax | grep '[t]tyd1'
您會見到類似這樣的結果:
747 ?? I 0:00.04 /usr/libexec/getty std.57600 ttyd1
如果您要把別的電腦當成是 FreeBSD 的終端機的話,您只需要在兩者的 serial port 之間牽一條 null modem 排線即可。如果您有一個真的終端機 的話,看看它的指令集吧。
然後,像上一個問題一樣修改 /etc/ttys 。舉例來說,如果您把一個 WYSE-50 終端機接在第五個 serial port 上的話,就要用這樣的設定:
ttyd4 "/usr/libexec/getty std.38400" wyse50 on secure
這個例子示範的是 /dev/ttyd4 所代表的 port 用的是 wyse50 終 端機,連線速度 38400 bps,不使用同位檢查 (std.38400 是從 /etc/gettytab 設定的) 而且 root 可以 login (secure) 。
事實上,tip 的 man page 已經過時了。一般的 Hayes dialer 已經內建在系 統內。您只要在 /etc/remote 指定 ``at=hayes'' 就可以了。
可惜的是,Hayes 的驅動程式不夠聰明,有些新 modem 上的進階功能它無法 辨識出來 --- 例如 BUSY ,NO DIALTONE ,或是 CONNECT 115200 這類的訊息它就會搞混。您在使用 tip 的時候必須 把它們關掉 (用 ATX0&W) 。
還有,tip 的 dial 逾時時間是 60 秒。您的 modem 可能要設得更短, 否則 tip 會認為發生了通訊上的問題。試試看ATS7=45&W 。
事實上 tip 還沒有完全支援它。解決方法是去修改 /usr/src/usr.bin/tip/tip 目錄裡的 tipconf.h 。很顯然您 必須要有原始程式碼才能這麼做。
把 ``#define HAYES 0'' 改成 ``#define HAYES 1'' 。然後 ``make'' 並 ``make install'' 。之後一切都會恢復正常了。
在您的 /etc/remote 檔裡加一個 ``direct'' 。舉例來說,如果您的 modem 連接在第一個 serial port,/dev/cuaa0,則您要加入下面 這一行:
cuaa0:dv=/dev/cuaa0:br#19200:pa=none
在 br 欄中設定您 modem 所支援的最高速。之後,鍵入 tip cuaa0 之後 您就連上您的 modem 了。
如果您的系統上沒有 /dev/cuaa0 ,您就先這樣:
# cd /dev
# ./MAKEDEV cuaa0
或是您可以用 root 執行 cu 指令,像這樣:
# cu -l``line'' -s``speed''
這裡的 line 是指您的 serial port (例如 /dev/cuaa0) ,speed 是指您的傳輸速度 (例如 57600) 。如果您下完 AT 指令後,鍵入 ~. 可以離開。
在您的 /etc/remote 放一個 ``generic''。舉例來說:
tip115200|Dial any phone number at 115200 bps:\
:dv=/dev/cuaa0:br#115200:at=hayes:pa=none:du:
tip57600|Dial any phone number at 57600 bps:\
:dv=/dev/cuaa0:br#57600:at=hayes:pa=none:du:
然後您就可以像 ``tip -115200 5551234'' 這樣用了。如果您比較喜 歡用 cu 的話,使用 generic cu 欄位:
cu115200|Use cu to dial any number at 115200bps:\
:dv=/dev/cuaa1:br#57600:at=hayes:pa=none:du:
然後輸入 ``cu 5551234 -s 115200'' 。
您可以使用類似 tip1200 或是 cu1200 的欄位,不過在您使用之 前請先確定您的 br 欄可以支援這個速度。tip 認為 1200 bps 是一個很好的預設值,這也就是為什麼要叫做 ``tip1200'' 的原因 了。當然您也可以不要用 1200 bps 。
除了每次等您連上 server 並鍵入 ``CONNECT <host>'' 以外, 比較好的方法是用 tip 的 cm 。舉例來說,看看 /etc/remote:
pain|pain.deep13.com|Forrester's machine:\
:cm=CONNECT pain\n:tc=deep13:
muffin|muffin.deep13.com|Frank's machine:\
:cm=CONNECT muffin\n:tc=deep13:
deep13:Gizmonics Institute terminal server:\
:dv=/dev/cua02:br#38400:at=hayes:du:pa=none:pn=5551234:
可以讓您只打 ``tip pain'' 或是 ``tip muffin'' 就可以連上 pain 或 muffin;然後 ``tip deep13'' 可以連上 terminal server。
通常這個問題發生在:一間大學有一些 modem,而且有上千名學生要用...
在 /etc/remote 裡為您的大學設一個欄位,並使用 [\@] 作為 它的 pn:
big-university:\
:pn=\@:tc=dialout
dialout:\
:dv=/dev/cuaa3:br#9600:at=courier:du:pa=none:
然後,把大學的撥接電話放在 /etc/phones 中:
big-university 5551111
big-university 5551112
big-university 5551113
big-university 5551114
tip 會依照表列的順序依次嚐試,最後放棄。如果您要一直試的話,您可以在 while 迴圈裡執行 tip 。
CTRL+P 是內定的 ``force'' 字元,用來告訴 tip 下一個字元 是一般字元。您可以藉由 ~s (代表 ``設定變數'') 把其他字元設成強 迫字元。
鍵入 ``~sforce=<single-char>'' 後面接一個 newline 。 <single-char> 可以是任意單一字元。如果您只打 <single-char> ,則 nul 就被設成是 force character,您可 以藉由按 CTRL+2 或是 CTRL+SPACE 來按出 nul 。SHIFT+CTRL+6 是一個不 錯的 <single-char> ,我看過一些終端機都是這麼設定。
您也可以在 $HOME/.tiprc 中設定 force character:
force=<single-char>
您應該是按到了 CTRL+A,在 tip 中為沒有 caps-lock 鍵的使用者所設計的 ``raise character''。您可以像上個問題 一樣利用 ~s 來把 ``raisechar'' 這個變數改成合理的值。事實上, 如果您認為您永遠都不會用到這兩個功能的話,您可以把它設成跟 force character 一樣。
下面是一個為 Emacs 使用者所設定的 .tiprc ,Emacs 使用者常常會用到 CTRL+2 和 CTRL+A:
force=^^
raisechar=^^
^ 就是 SHIFT+CTRL+6 。
如果您的主機板或是卡上有用到 Acer 的 UART 晶片的話,FreeBSD 在開機時 的 sio 偵測可能會不正確。您可以從 www.lemis.com 找到 patch 來修正這個問題。