Bài viết này giải thích liệu bạn có thể sử dụng **I/O ports** (sử dụng các lệnh `in`, `out` trong assembly) để truyền dữ liệu qua **PCI Express** trên các CPU x86_64 hiện đại hay không. Chúng ta sẽ đi sâu vào các khái niệm như **BARs (Base Address Registers)**, **MMIO (Memory Mapped I/O)**, **DMA (Direct Memory Access)** và khả năng tương thích ngược với ISA để bạn có cái nhìn toàn diện về vấn đề này. Nếu bạn là một nhà phát triển phần cứng hoặc phần mềm hệ thống, bài viết này sẽ cung cấp thông tin quan trọng để hiểu cách các thiết bị ngoại vi giao tiếp với CPU.
Các bus dựa trên PCI, bao gồm cả **PCI Express**, hỗ trợ ba không gian địa chỉ khác nhau: không gian địa chỉ bộ nhớ, không gian địa chỉ **I/O**, và không gian địa chỉ cấu hình. Trên các máy tính x86, không gian địa chỉ bộ nhớ được ánh xạ gần như 1:1 với không gian địa chỉ vật lý của CPU. Tương tự, không gian địa chỉ **I/O** được ánh xạ 1:1 với không gian địa chỉ **I/O** của CPU. Không gian địa chỉ cấu hình được ánh xạ vào một vị trí cố định trong không gian địa chỉ vật lý, được chọn bởi BIOS khi khởi động.
Điều này có nghĩa là các lệnh `IN/OUT` của x86 có thể truy cập các thiết bị **PCI Express**, nhưng chỉ khi thiết bị đó thực sự phân bổ một phần của không gian địa chỉ **I/O**. Thông thường, các thiết bị thực hiện điều này là những thiết bị tương thích ngược với các card ISA. Ví dụ: một card serial **PCI Express** sẽ cung cấp một giao diện tương thích với UART 8250 thông qua không gian **I/O**, để nó có thể được sử dụng với các trình điều khiển cổng serial tiêu chuẩn. Nếu nó sử dụng **MMIO** thay thế, thiết bị sẽ yêu cầu trình điều khiển tùy chỉnh riêng.
Các thiết bị **PCI Express** khác vẫn sử dụng không gian **I/O**, bao gồm các thiết bị hiện đại như card đồ họa (để tương thích VGA) và giao diện SATA (để tương thích IDE). Bất kỳ thiết bị mới nào không cần hỗ trợ legacy sẽ sử dụng **MMIO** độc quyền. Không có lợi thế nào khác ngoài khả năng tương thích ngược khi sử dụng không gian địa chỉ **I/O**.
Ví dụ, card đồ họa có thể sử dụng **I/O ports** cho các chức năng VGA cổ điển, trong khi sử dụng **MMIO** cho các chức năng hiện đại hơn như tăng tốc đồ họa 3D. Tương tự, một bộ điều khiển SATA có thể sử dụng **I/O ports** để tương thích với các trình điều khiển IDE cũ, nhưng sử dụng **MMIO** cho các hoạt động SATA Native Command Queuing (NCQ) hiệu quả hơn.
Việc sử dụng **BARs** thường bị hiểu sai. Các **BARs** (Base Address Registers) được hệ điều hành (hoặc BIOS/firmware) sử dụng để phân bổ các vùng bộ nhớ và/hoặc không gian **I/O** cho thiết bị. Chúng tồn tại trong không gian địa chỉ cấu hình và không thể được sử dụng để truyền dữ liệu. Ví dụ, một card serial **PCI Express** sẽ có một **BAR** xác định vị trí các thanh ghi tương thích 8450 của nó được ánh xạ vào không gian **I/O**. Hệ điều hành sẽ ánh xạ chúng vào một vị trí không được sử dụng bởi bất kỳ thiết bị nào khác.
Trong khi trên một PC, hệ điều hành sẽ sử dụng **MMIO** để đọc và ghi vào các **BARs**, thì trình điều khiển sẽ không. Để truyền dữ liệu, trình điều khiển sẽ truy cập các vùng bộ nhớ **PCI** hoặc không gian **I/O** đã được phân bổ cho thiết bị thông qua các **BARs**. Các vùng này sẽ chứa các thanh ghi được sử dụng trực tiếp để truyền dữ liệu, các thanh ghi để thiết lập **DMA** để thực hiện việc truyền, hoặc được ánh xạ tới RAM trên thiết bị nơi dữ liệu được giữ.
Cũng có thể sử dụng một phần của không gian cấu hình **PCI** của thiết bị làm các thanh ghi dành riêng cho thiết bị để thực hiện việc truyền, cấu hình hoặc bất cứ điều gì khác. Một card serial **PCI Express** không tương thích ngược giả định có thể sẽ không định nghĩa bất kỳ **BARs** nào và thay vào đó ánh xạ các thanh ghi UART của nó trong không gian cấu hình của nó.
Ngày nay, **I/O ports** hiếm khi được sử dụng vì giao diện sử dụng chúng vốn rất chậm. Số lượng cổng có thể định địa chỉ cũng rất hạn chế. Tuy nhiên, liệu thiết bị cụ thể của bạn có yêu cầu **I/O ports** hay không phụ thuộc vào việc triển khai phần cứng. Về cơ bản, kiến trúc dường như cho phép cả việc định địa chỉ dựa trên **I/O port** cho các thiết bị **PCIe**, ví dụ như card đồ họa vẫn dành riêng một số cổng.
Cần lưu ý rằng việc trực tiếp phát hành các lệnh `in` hoặc `out` từ mã người dùng trong một hệ điều hành hiện đại sẽ gây ra lỗi bảo vệ, vì các lệnh này được dành riêng cho mã trình điều khiển. Bạn sẽ cần đặc quyền đặc biệt để truy cập **I/O port**.
Tóm lại, việc sử dụng **I/O ports** qua **PCI Express** trên các CPU x86_64 hiện đại là có thể, nhưng nó chủ yếu giới hạn ở các thiết bị cần tương thích ngược với ISA. Các thiết bị mới hơn thường sử dụng **MMIO** cho hiệu suất và tính linh hoạt tốt hơn. Hiểu rõ về **BARs** và cách chúng được sử dụng để phân bổ không gian địa chỉ là rất quan trọng để làm việc với các thiết bị **PCI Express** ở cấp độ hệ thống.
Bài viết liên quan